<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Leon Stigter</title>
    <description>The latest articles on Forem by Leon Stigter (@retgits).</description>
    <link>https://forem.com/retgits</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F92249%2Fbd7ebdd9-f0fe-4476-b950-c204dfb3e22a.png</url>
      <title>Forem: Leon Stigter</title>
      <link>https://forem.com/retgits</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/retgits"/>
    <language>en</language>
    <item>
      <title>How To Set Up Continuous Integration and Delivery With Github Actions and Akka Serverless</title>
      <dc:creator>Leon Stigter</dc:creator>
      <pubDate>Tue, 01 Jun 2021 00:00:00 +0000</pubDate>
      <link>https://forem.com/retgits/how-to-set-up-continuous-integration-and-delivery-with-github-actions-and-akka-serverless-2mjg</link>
      <guid>https://forem.com/retgits/how-to-set-up-continuous-integration-and-delivery-with-github-actions-and-akka-serverless-2mjg</guid>
      <description>&lt;p&gt;CI/CD is one of those quintessential mindset shifts that helps developers automate away the toil of deploying apps. Especially in the realm of serverless, where the whole idea is to focus on the things that matter and let the undifferentiated heavy lifting be handled by others, automating as much as possible is paramount. It helps developers focus on what matters, code, and it helps business focus on what matters, getting quality software to market faster. So how does that work in &lt;a href="https://akkaserverless.com"&gt;Akka Serverless&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://akkaserverless.com"&gt;Akka Serverless&lt;/a&gt; focuses on bringing together the worlds of Functions-as-a-Service and serverless databases into a single package. That single package allows developers to focus on code even more as they no longer have to worry about the database. In this short blog post, I’ll walk you through automating the CI and CD workflow for Akka Serverless using &lt;a href="https://github.com/features/actions"&gt;GitHub Actions&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The GitHub Actions
&lt;/h2&gt;

&lt;p&gt;In the CI/CD I’ll use four different GitHub Actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/marketplace/actions/docker-login"&gt;Docker Login&lt;/a&gt; so I can publish the resulting container to Docker Hub (or any other supported Docker registry)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/marketplace/actions/docker-setup-buildx"&gt;Docker Setup Buildx&lt;/a&gt; which uses BuildKit and makes it possible to create multi-platform images (which is out of scope for this blog post)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/marketplace/actions/build-and-push-docker-images"&gt;Build and push Docker images&lt;/a&gt; to push the resulting image to Docker Hub&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/marketplace/actions/akkasls"&gt;Akka Serverless CLI for GitHub Actions&lt;/a&gt; to deploy to Akka Serverless&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To make all the actions work, and to make it a little more secure, it’s best to set up usernames, passwords, and authentication tokens as secrets in GitHub. Under &lt;code&gt;Settings -&amp;gt; Secrets&lt;/code&gt; I’ve created four environment variables that have been encrypted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DOCKERHUB_TOKEN: the &lt;a href="https://docs.docker.com/docker-hub/access-tokens/"&gt;personal authentication&lt;/a&gt; token to log in to Docker Hub (while you could use a password too, it’s strongly recommended to use a personal access token)&lt;/li&gt;
&lt;li&gt;DOCKERHUB_USERNAME: the username to log in to Docker Hub&lt;/li&gt;
&lt;li&gt;PROJECT: the ID of the project I want to deploy to on Akka Serverless (&lt;code&gt;akkasls projects get &amp;lt;project name&amp;gt;&lt;/code&gt; will show the ID of the project in the ID column)&lt;/li&gt;
&lt;li&gt;TOKEN: the Akka Serverless &lt;a href="https://developer.lightbend.com/docs/akka-serverless/deploying/integrate-cicd.html"&gt;authentication token&lt;/a&gt; that the action will use to connect to Akka Serverless (to create a token with “&lt;em&gt;execution&lt;/em&gt;” scope, the command I need to run is &lt;code&gt;akkasls auth tokens create --type=refresh --scopes=execution --description="My CI/CD token"&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qFprXpaC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://retgits.com/images/set-continuous-integration-delivery-github-actions-akka-serverless-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qFprXpaC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://retgits.com/images/set-continuous-integration-delivery-github-actions-akka-serverless-1.png" alt="github secrets" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The YAML
&lt;/h2&gt;

&lt;p&gt;After setting up the four secrets, the only thing left is to create the GitHub Actions YAML configuration. I’ll start with the complete file first, and break it into sections to explain what everything does. The file should be stored in the &lt;code&gt;.github/workflows&lt;/code&gt; folder of the repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  The full file
&lt;/h3&gt;

&lt;p&gt;In my case, I’ve named my file &lt;code&gt;deploy.yaml&lt;/code&gt; and stored it in the &lt;code&gt;.github/workflows&lt;/code&gt; folder of my repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: akkasls-deployer

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1
      - name: Login to Docker Hub
        uses: docker/login-action@v1
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      - name: Build and push to Docker Hub
        uses: docker/build-push-action@v2
        with:
          push: true
          tags: retgits/myapp:1.0.0
      - name: Deploy to Akka Serverless
        uses: retgits/akkasls-action@v1
        with:
          cmd: "services deploy myapp retgits/myapp:1.0.0"
        env:
          token: ${{ secrets.TOKEN }}
          project: ${{ secrets.PROJECT }}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Breaking up the file in parts
&lt;/h3&gt;

&lt;p&gt;Now that you can see the entire file, I’ll break it up into smaller sections to explain what they do.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: akkasls-deployer

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AqLc1T7X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://retgits.com/images/set-continuous-integration-delivery-github-actions-akka-serverless-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AqLc1T7X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://retgits.com/images/set-continuous-integration-delivery-github-actions-akka-serverless-2.png" alt="workflow name" width="800" height="180"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This basically determines the name of the workflow and this is how it shows up in the &lt;strong&gt;Actions&lt;/strong&gt; section of the repository&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;on:
  push:
    branches: [main]
  workflow_dispatch:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;on&lt;/strong&gt; section of a workflow describes the triggers, or when the workflow is executed. In this case, the workflow is executed every time there is a &lt;code&gt;push&lt;/code&gt; to the &lt;code&gt;main&lt;/code&gt; branch or when it is triggered from the workflow (which is done by the &lt;code&gt;workflow_dispatch&lt;/code&gt; setting and is useful if you want to trigger the workflow without pushing to the main branch).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7zR0_jV9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://retgits.com/images/set-continuous-integration-delivery-github-actions-akka-serverless-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7zR0_jV9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://retgits.com/images/set-continuous-integration-delivery-github-actions-akka-serverless-3.png" alt="dispatch trigger" width="800" height="115"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jobs:
  build:
    runs-on: ubuntu-latest

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I run all my builds on Ubuntu, though you could opt to use different operating systems, or even use a self-hosted runner.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;steps:
  - name: Checkout
    uses: actions/checkout@v2

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step checks out the code, so the other steps in this workflow can use it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  - name: Set up Docker Buildx
    uses: docker/setup-buildx-action@v1

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step sets up &lt;strong&gt;Buildx&lt;/strong&gt; so I can build different images for different operating systems if I wanted (which is especially useful if you want to build containers that run on Apple Silicon chips)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  - name: Login to Docker Hub
    uses: docker/login-action@v1
    with:
      username: ${{ secrets.DOCKERHUB_USERNAME }}
      password: ${{ secrets.DOCKERHUB_TOKEN }}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As the name implies, this step logs in to Docker Hub so the resulting container image can be pushed there. It leverages two of the &lt;strong&gt;Secrets&lt;/strong&gt; created earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  - name: Build and push to Docker Hub
    uses: docker/build-push-action@v2
    with:
      push: true
      tags: retgits/myapp:1.0.0

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step builds the container and pushes it to Docker Hub, calling it &lt;code&gt;retgits/myapp:1.0.0&lt;/code&gt;. This is obviously where you want to use some parameterization and use the name of the tag, the GitHub commit SHA, or something else to uniquely identify the container image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  - name: Deploy to Akka Serverless
    uses: retgits/akkasls-action@v1
    with:
      cmd: "services deploy myapp retgits/myapp:1.0.0"
    env:
      token: ${{ secrets.TOKEN }}
      project: ${{ secrets.PROJECT }}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last step in the process is to deploy the container image to Akka Serverless. This step leverages the other two &lt;strong&gt;Secrets&lt;/strong&gt; created earlier, and it uses the same tag as in the previous step.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;As you can see, using CI/CD to deploy a service to Akka Serverless is pretty straight-forward and setting it up once saves a lot of hassle down the line. Let me know what you want to see next, or what you want us to build next!&lt;/p&gt;

&lt;p&gt;Cover photo by &lt;a href="https://pixabay.com/users/geralt-9301"&gt;Gerd Altmann&lt;/a&gt; from &lt;a href="https://pixabay.com"&gt;Pixabay&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>serverless</category>
      <category>lightbend</category>
    </item>
    <item>
      <title>How To Build Infrastructure as Code With Pulumi And Golang - Part 2</title>
      <dc:creator>Leon Stigter</dc:creator>
      <pubDate>Thu, 06 Feb 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/retgits/how-to-build-infrastructure-as-code-with-pulumi-and-golang-part-2-266l</link>
      <guid>https://forem.com/retgits/how-to-build-infrastructure-as-code-with-pulumi-and-golang-part-2-266l</guid>
      <description>&lt;p&gt;Going into the series on creating Infrastructure as Code on AWS using &lt;a href="https://pulumi.com"&gt;Pulumi&lt;/a&gt;, I knew the team there was actively working on improving and expanding the Go support in Pulumi. What I didn’t realize is that it would be so quick and would be such a great improvement to the underlying code I needed to write. In this post, I’ll go over some of the code from my previous blog posts and update them to match the new SDK.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The complete project is available on &lt;a href="https://github.com/retgits/pulumi-blogs/tree/part2-blog"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The core &lt;a href="https://www.pulumi.com/docs/intro/concepts/programming-model"&gt;programming model&lt;/a&gt; in Pulumi has tons of really awesome features, but not all of them are available in the Go SDK yet. The work the team at Pulumi is currently doing, includes some significant changes to the SDK, including more strongly typed structs (no more &lt;code&gt;interface{}&lt;/code&gt;, yay! 🥳), better support for Input and Output types, and making sure the Go has the same features from the core programming model as the other languages do. With so many changes going in, it’s almost impossible to not make breaking changes. Pulumi suggests that Go devs pin the versions of the SDK they’re currently using.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;TL;DR I had to make a bunch of changes to make sure all the code worked again (like adding &lt;code&gt;pulumi.String()&lt;/code&gt; wrappers around strings) but I could also replace all my own structs with structs from the Pulumi SDK. There are a few rough edges, but then again it is a work in progress and I’m excited to see what’s next.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;One of the new features that were added, or perhaps I just didn’t realize it existed before, is the ability to read and parse configuration from the YAML file. Using that configuration you can parameterize your stack based on config from a file, rather than hard coding it.&lt;/p&gt;

&lt;p&gt;In the previous version of the code, I wrote my own function to get the configuration variables from the context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// getEnv searches for the requested key in the pulumi context and provides either the value of the key or the fallback.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fallback&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fallback&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That piece of the code, and a lot of related helper functions, can now be removed. In the snippet below, I’ve created a &lt;em&gt;VPCConfig&lt;/em&gt; struct which, through the &lt;code&gt;RequireObject()&lt;/code&gt; method, is populated with data from the Pulumi YAML file. The nice thing about this approach is that the &lt;code&gt;RequireObject()&lt;/code&gt; method means that the object with that name needs to exist, otherwise Pulumi will throw an error and you can model your structs (and configuration data) to actually match the types they should be. Rather than having comma separated lists, I now have proper YAML arrays.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// VPCConfig is a strongly typed struct that can be populated with&lt;/span&gt;
&lt;span class="c"&gt;// contents from the YAML file. These are the configuration items&lt;/span&gt;
&lt;span class="c"&gt;// to create a VPC.&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;VPCConfig&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;CIDRBlock&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"cidr-block"`&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;SubnetIPs&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"subnet-ips"`&lt;/span&gt;
    &lt;span class="n"&gt;SubnetZones&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"subnet-zones"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Create a new config object with the data from the YAML file&lt;/span&gt;
        &lt;span class="c"&gt;// The object has all the data that the namespace awsconfig has&lt;/span&gt;
        &lt;span class="n"&gt;conf&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"awsconfig"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;vpcConfig&lt;/span&gt; &lt;span class="n"&gt;VPCConfig&lt;/span&gt;
        &lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequireObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"vpc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;vpcConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;vpcArgs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ec2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VpcArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;CidrBlock&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vpcConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CIDRBlock&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;Tags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tagMap&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="c"&gt;// snip&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These changes in the code also mean that the configuration file itself looks a lot cleaner. The snippet below shows what it was with the previous version of my code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;vpc:name: myPulumiVPC&lt;/span&gt;
&lt;span class="s"&gt;vpc:cidr-block: "172.32.0.0/16"&lt;/span&gt;
&lt;span class="s"&gt;vpc:subnet-zones: "us-east-1a,us-east-1c"&lt;/span&gt;
&lt;span class="s"&gt;vpc:subnet-ips: "172.32.32.0/20,172.32.80.0/20"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which is now replaced by better looking, and easier to read, YAML&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;awsconfig:vpc:&lt;/span&gt;
    &lt;span class="s"&gt;cidr-block&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;172.32.0.0/16&lt;/span&gt;
    &lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myPulumiVPC&lt;/span&gt;
    &lt;span class="s"&gt;subnet-ips&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;172.32.32.0/20&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;172.32.80.0/20&lt;/span&gt;
    &lt;span class="na"&gt;subnet-zones&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;us-east-1a&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;us-east-1c&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are perhaps a few more lines, but the benefits of seeing which configuration items are actually arrays is super useful. The only thing that struck me as a little odd, is that you write the config in a YAML file and the struct tags use JSON.&lt;/p&gt;

&lt;h2&gt;
  
  
  Type Safety
&lt;/h2&gt;

&lt;p&gt;One of the reasons I like Go is that it is a strongly typed language. That means that the type of variable is specified when you’re building your app. In the previous version of my code, I created my own structs to help add some strongly typed structs to create a DynamoDB table. The code below is a snippet of that code that shows the &lt;em&gt;“old”&lt;/em&gt; way, where I had my own struct.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// DynamoAttribute represents an attribute for describing the key schema for the table and indexes.&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;DynamoAttribute&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// DynamoAttributes is an array of DynamoAttribute&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;DynamoAttributes&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;DynamoAttribute&lt;/span&gt;

&lt;span class="c"&gt;// ToList takes a DynamoAttributes object and turns that into a slice of map[string]interface{} so it can be correctly passed to the Pulumi runtime&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="n"&gt;DynamoAttributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;
        &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Create the attributes for ID and User&lt;/span&gt;
&lt;span class="n"&gt;dynamoAttributes&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;DynamoAttributes&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;DynamoAttribute&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"S"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;DynamoAttribute&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"S"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The updates to the Pulumi SDK introduced a ton of strongly typed structs that remove the need to have those helper structs and methods. In my case, for the DynamoDB table, there are now structs that support the Table Attributes and Global Secondary Indices. Removing the helper methods and replacing that with structs from the Pulumi SDK meant I went down from roughly 33 lines of code to 10 lines. I’m quite sure that feature alone will make sure I write better and cleaner code. The code snippet below shows the same attributes and does the same thing as the above snippet did.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Create the attributes for ID and User&lt;/span&gt;
&lt;span class="n"&gt;dynamoAttributes&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;dynamodb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TableAttributeInput&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;dynamodb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TableAttributeArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ID"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"S"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;dynamodb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TableAttributeArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"S"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to deploy your AWS Lambda functions through Pulumi, the same benefits I talked about are absolutely true for Lambda as well. More strongly typed structs with clear field definitions means that writing code is a lot easier and cleaner. Because you don’t have to rely on a bunch of helper methods, it also makes the code simpler to understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Going forward
&lt;/h2&gt;

&lt;p&gt;Does all of this mean it’s all roses, though, the engineers at Pulumi still have some things to do. Credit to them, they do all of that &lt;a href="https://github.com/pulumi/pulumi/issues/1614"&gt;out in the open&lt;/a&gt;. For me personally, I was very excited to see how far the team at Pulumi has come over the past few weeks. While there are a few rough edges, like documentation for the inputs and outputs of certain methods, I’m sure the team will update those in new releases, together with the help of the amazing community. I for one am excited to see how Pulumi takes Infrastructure as Code to a new level for Go developers.&lt;/p&gt;

</description>
      <category>go</category>
      <category>devops</category>
    </item>
    <item>
      <title>How To Create AWS Lambda Functions Using Pulumi And Golang</title>
      <dc:creator>Leon Stigter</dc:creator>
      <pubDate>Tue, 28 Jan 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/retgits/how-to-create-aws-lambda-functions-using-pulumi-and-golang-2b5e</link>
      <guid>https://forem.com/retgits/how-to-create-aws-lambda-functions-using-pulumi-and-golang-2b5e</guid>
      <description>&lt;p&gt;I’ve looked at &lt;a href="https://pulumi.com"&gt;Pulumi&lt;/a&gt; to do a bunch of things, including &lt;a href="https://retgits.com/2020/01/how-to-add-subnets-to-a-vpc-in-aws-using-pulumi-and-golang/"&gt;creating subnets in a VPC&lt;/a&gt;, &lt;a href="https://retgits.com/2020/01/how-to-create-an-aws-eks-cluster-using-pulumi-and-golang/"&gt;building EKS clusters&lt;/a&gt;, and &lt;a href="https://retgits.com/2020/01/how-to-create-a-dynamodb-in-aws-using-pulumi-and-golang/"&gt;DynamoDB tables&lt;/a&gt;. The one thing I hadn’t explored yet was how to deploy AWS Lambda functions using Pulumi, so that’s exactly what this blog is about.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The complete project is available on &lt;a href="https://github.com/retgits/pulumi-blogs/tree/lambda-blog"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Lambda
&lt;/h2&gt;

&lt;p&gt;The Lambda function for this post is a rather simple one, it says &lt;em&gt;“Hello”&lt;/em&gt; to whatever the value of an environment variable will be.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "os"

    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
)

func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    val := os.Getenv("NAME")
    return events.APIGatewayProxyResponse{
        Body: fmt.Sprintf("Hello, %s", val),
        StatusCode: 200,
    }, nil
}

func main() {
    lambda.Start(handler)
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That code is in a file called &lt;strong&gt;hello-world.go&lt;/strong&gt; , which is in a folder called &lt;strong&gt;hello-world&lt;/strong&gt;. The Pulumi project is inside the folder called &lt;strong&gt;Pulumi&lt;/strong&gt; so it will be a separate folder structure and not collide with the other code of your Lambda functions. The folder structure, including all the files looks like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── README.md
├── go.mod
├── go.sum
└── hello-world
│ └── main.go
├── pulumi
│ ├── Pulumi.lambdastack.yaml
│ ├── Pulumi.yaml
    └── main.go

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Building and uploading your Lambda code
&lt;/h2&gt;

&lt;p&gt;In order to deploy a Lambda function, the code needs to be uploaded as well. While Pulumi has the concept of an Archive to create the zip file, the Go implementation has a &lt;a href="https://github.com/pulumi/pulumi/issues/1962"&gt;known issue&lt;/a&gt; which makes it impossible to use that feature. Rather than manually building, zipping, and uploading the code, you can extend the Pulumi program a little to do all of that before the program runs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const (
    shell = "sh"
    shellFlag = "-c"
    rootFolder = "/rootfolder/of/your/lambdaapp"
)

func runCmd(args string) error {
    cmd := exec.Command(shell, shellFlag, args)
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    cmd.Dir = rootFolder
    return cmd.Run()
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;runCmd&lt;/code&gt; method will run a specific command and will return either an error or a &lt;em&gt;nil&lt;/em&gt; object. To build, zip, and upload your Go code to S3 you can add the below snippets to your Pulumi project. It uses the above function to run the three commands you would normally script as part of your CI/CD or test framework. These commands should be pasted before &lt;code&gt;pulumi.Run()&lt;/code&gt; gets invoked.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if err := runCmd("GOOS=linux GOARCH=amd64 go build -o hello-world/hello-world ./hello-world"); err != nil {
    fmt.Printf("Error building code: %s", err.Error())
    os.Exit(1)
}

if err := runCmd("zip -r -j ./hello-world/hello-world.zip ./hello-world/hello-world"); err != nil {
    fmt.Printf("Error creating zipfile: %s", err.Error())
    os.Exit(1)
}

if err := runCmd("aws s3 cp ./hello-world/hello-world.zip s3://&amp;lt;your-bucket&amp;gt;/hello-world.zip"); err != nil {
    fmt.Printf("Error creating zipfile: %s", err.Error())
    os.Exit(1)
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If these commands fail, you’ll be able to see the output and the error message as part of the &lt;em&gt;“diagnostics”&lt;/em&gt; section in your terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating an IAM role
&lt;/h2&gt;

&lt;p&gt;Every Lambda function, and most other AWS resources as well, need an IAM role to be able to work. The IAM role gives the resources the permissions to act on your behalf. This Lambda function doesn’t have a lot of specifics it needs to do, other than be able to run. To create an IAM role with that permission, you can use the below code. The ARN (&lt;a href="https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html"&gt;Amazon Resource Name&lt;/a&gt;), is exported so that it is visible from within the Pulumi console.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// The policy description of the IAM role, in this case only the sts:AssumeRole is needed
roleArgs := &amp;amp;iam.RoleArgs{
    AssumeRolePolicy: `{
        "Version": "2012-10-17",
        "Statement": [
        {
            "Action": "sts:AssumeRole",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Effect": "Allow",
            "Sid": ""
        }
        ]
    }`,
}

// Create a new role called HelloWorldIAMRole
role, err := iam.NewRole(ctx, "HelloWorldIAMRole", roleArgs)
if err != nil {
    fmt.Printf("role error: %s\n", err.Error())
    return err
}

// Export the role ARN as an output of the Pulumi stack
ctx.Export("Role ARN", role.Arn())

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting environment variables
&lt;/h2&gt;

&lt;p&gt;Just like in CloudFormation, the Pulumi SDK allows you to create a set of environment variables. That’s a good thing, because the Lambda function relies on an environment variable called &lt;em&gt;“NAME”&lt;/em&gt; to know who to greet. The environment variables are a &lt;code&gt;map[string]interface{}&lt;/code&gt; inside a &lt;code&gt;map[string]interface{}&lt;/code&gt;. For this Lambda function, that would be the below snippet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;environment := make(map[string]interface{})
variables := make(map[string]interface{})
variables["NAME"] = "WORLD"
environment["variables"] = variables

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating the function
&lt;/h2&gt;

&lt;p&gt;The last step. at least for this code, is to actually create the Lambda function. The &lt;strong&gt;S3Bucket&lt;/strong&gt; and &lt;strong&gt;S3Key&lt;/strong&gt; are the name of the bucket and the name of the file you’ve uploaded earlier in the process. The &lt;strong&gt;role.Arn()&lt;/strong&gt; is the ARN of the role that was created in the previous step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// The set of arguments for constructing a Function resource.
functionArgs := &amp;amp;lambda.FunctionArgs{
    Description: "My Lambda function",
    Runtime: "go1.x",
    Name: "HelloWorldFunction",
    MemorySize: 256,
    Timeout: 10,
    Handler: "hello-world",
    Environment: environment,
    S3Bucket: "&amp;lt;your-bucket&amp;gt;",
    S3Key: "hello-world.zip",
    Role: role.Arn(),
}

// NewFunction registers a new resource with the given unique name, arguments, and options.
function, err := lambda.NewFunction(ctx, "HelloWorldFunction", functionArgs)
if err != nil {
    fmt.Println(err.Error())
    return err
}

// Export the function ARN as an output of the Pulumi stack
ctx.Export("Function", function.Arn())

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running Pulumi up
&lt;/h2&gt;

&lt;p&gt;With all the code ready, it’s time to run &lt;code&gt;pulumi up&lt;/code&gt; and deploy the Lambda function to AWS. If you need more details on how to create a Go project for Pulumi, check out &lt;a href="https://retgits.com/2020/01/how-to-create-a-vpc-in-aws-using-pulumi-and-golang/"&gt;this&lt;/a&gt; post.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pulumi up
Previewing update (lambda):

     Type Name Plan Info
 + pulumi:pulumi:Stack lambda-lambda create 2 messages
 + ├─ aws:iam:Role HelloWorldIAMRole create     
 + └─ aws:lambda:Function HelloWorldFunction create     

Diagnostics:
  pulumi:pulumi:Stack (lambda-lambda):
    updating: hello-world/hello-world (deflated 49%)
upload: hello-world/hello-world.zip to s3://&amp;lt;your-bucket&amp;gt;/hello-world.zip

Resources:
    + 3 to create

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

     Type Name Status Info
 + pulumi:pulumi:Stack lambda-lambda created 2 messages
 + ├─ aws:iam:Role HelloWorldIAMRole created     
 + └─ aws:lambda:Function HelloWorldFunction created     

Diagnostics:
  pulumi:pulumi:Stack (lambda-lambda):
    updating: hello-world/hello-world (deflated 49%)
upload: hello-world/hello-world.zip to s3://&amp;lt;your-bucket&amp;gt;/hello-world.zip

Outputs:
    Function: "arn:aws:lambda:us-west-2:ACCOUNTID:function:HelloWorldFunction"
    Role ARN: "arn:aws:iam::ACCOUNTID:role/HelloWorldIAMRole-7532034"

Resources:
    + 3 created

Duration: 44s

Permalink: https://app.pulumi.com/retgits/lambda/lambda/updates/1

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing with the AWS Console
&lt;/h2&gt;

&lt;p&gt;Inside the Pulumi console, you’ll be able to see the resources that have been created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r8o_2TDO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://retgits.com/images/how-to-create-lambdas-in-aws-using-pulumi-and-golang-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r8o_2TDO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://retgits.com/images/how-to-create-lambdas-in-aws-using-pulumi-and-golang-1.png" alt="The Pulumi console also has really useful links to the AWS console to see the resources." width="800" height="244"&gt;&lt;/a&gt;&lt;br&gt;
            &lt;p&gt;The Pulumi console also has really useful links to the AWS console to see the resources.&lt;/p&gt;

 &lt;/p&gt;

&lt;p&gt;Within the AWS Lambda console, you’ll be able to test the function and see that it indeed responds with the greeting &lt;em&gt;“Hello, WORLD”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S9aiV08d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://retgits.com/images/how-to-create-lambdas-in-aws-using-pulumi-and-golang-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S9aiV08d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://retgits.com/images/how-to-create-lambdas-in-aws-using-pulumi-and-golang-2.png" alt="The AWS Lambda console." width="800" height="212"&gt;&lt;/a&gt;&lt;br&gt;
            &lt;p&gt;The AWS Lambda console.&lt;/p&gt;

 &lt;/p&gt;

</description>
      <category>go</category>
      <category>devops</category>
      <category>serverless</category>
    </item>
    <item>
      <title>How To Create a DynamoDB Table In AWS Using Pulumi And Golang</title>
      <dc:creator>Leon Stigter</dc:creator>
      <pubDate>Tue, 21 Jan 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/retgits/how-to-create-a-dynamodb-table-in-aws-using-pulumi-and-golang-4308</link>
      <guid>https://forem.com/retgits/how-to-create-a-dynamodb-table-in-aws-using-pulumi-and-golang-4308</guid>
      <description>&lt;p&gt;In &lt;a href="https://retgits.com/2020/01/how-to-add-subnets-to-a-vpc-in-aws-using-pulumi-and-golang/"&gt;previous&lt;/a&gt; &lt;a href="https://retgits.com/2020/01/how-to-make-your-aws-eks-cluster-use-fargate-using-pulumi-and-golang/"&gt;posts&lt;/a&gt;, I looked at &lt;a href="https://pulumi.com/"&gt;Pulumi&lt;/a&gt; to do all sorts of things with infrastructure. Most apps, though, will need some form of datastore so in this post I’ll go over the steps to create a DynamoDB table in AWS using Pulumi.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The complete project is available on &lt;a href="https://github.com/retgits/pulumi-blogs/tree/dynamodb-blog"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Static types
&lt;/h2&gt;

&lt;p&gt;One of the main advantages of programming languages like Golang and Java is that those languages have static types that make development less error prone. As developers are writing the code, they know what the input and output of methods will be. Unfortunately, the Go SDK for Pulumi doesn’t yet offer static types for AWS resources. The snippet of code below has two types (&lt;code&gt;DynamoAttribute&lt;/code&gt; and &lt;code&gt;GlobalSecondaryIndex&lt;/code&gt;) that represent the static types of the DynamoDB constructs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// DynamoAttribute represents an attribute for describing the key schema for the table and indexes.&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;DynamoAttribute&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// DynamoAttributes is an array of DynamoAttribute&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;DynamoAttributes&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;DynamoAttribute&lt;/span&gt;

&lt;span class="c"&gt;// GlobalSecondaryIndex represents the properties of a global secondary index&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;GlobalSecondaryIndex&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;HashKey&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;ProjectionType&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;WriteCapacity&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;ReadCapacity&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// GlobalSecondaryIndexes is an array of GlobalSecondaryIndex&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;GlobalSecondaryIndexes&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;GlobalSecondaryIndex&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The input to create a DynamoDB table, the &lt;a href="https://godoc.org/github.com/pulumi/pulumi-aws/sdk/go/aws/dynamodb#TableArgs"&gt;tableArgs&lt;/a&gt;, expects a &lt;strong&gt;interface{}&lt;/strong&gt; for these two fields and the underlying infrastructure expects that interface{} to be a &lt;em&gt;list&lt;/em&gt; (or a slice of interfaces to use the correct Go terminology). To make that that type conversion happen, you can use the below two &lt;code&gt;ToList()&lt;/code&gt; methods for the types above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// ToList takes a DynamoAttributes object and turns that into a slice of map[string]interface{} so it can be correctly passed to the Pulumi runtime&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="n"&gt;DynamoAttributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;
        &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// ToList takes a GlobalSecondaryIndexes object and turns that into a slice of map[string]interface{} so it can be correctly passed to the Pulumi runtime&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;GlobalSecondaryIndexes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"hash_key"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HashKey&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"projection_type"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProjectionType&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"write_capacity"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteCapacity&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"read_capacity"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadCapacity&lt;/span&gt;
        &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above two methods make it easier to use static typed objects in your code, while still being able to use the Pulumi runtime to create your DynamoDB tables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a table
&lt;/h2&gt;

&lt;p&gt;The next step is to bring all of that together and create the table. In this sample I’ve used a table with usernames and unique IDs, that I use in one of my apps to keep track of order data. Since the actual order data isn’t modeled here, you won’t be able to use it in your queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Create the attributes for ID and User&lt;/span&gt;
&lt;span class="n"&gt;dynamoAttributes&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;DynamoAttributes&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;DynamoAttribute&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"S"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;DynamoAttribute&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"S"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Create a Global Secondary Index for the user field&lt;/span&gt;
&lt;span class="n"&gt;gsi&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;GlobalSecondaryIndexes&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;GlobalSecondaryIndex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;HashKey&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;ProjectionType&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"ALL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;WriteCapacity&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;ReadCapacity&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Create a TableArgs struct that contains all the data&lt;/span&gt;
&lt;span class="n"&gt;tableArgs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;dynamodb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TableArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Attributes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dynamoAttributes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;HashKey&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;WriteCapacity&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ReadCapacity&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;GlobalSecondaryIndexes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;gsi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Let the Pulumi runtime create the table&lt;/span&gt;
&lt;span class="n"&gt;userTable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;dynamodb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tableArgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Export the name of the newly created table as an output in the stack&lt;/span&gt;
&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TableName"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userTable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Complete code
&lt;/h2&gt;

&lt;p&gt;Combining all of the above into a single, runnable, Go program&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/pulumi/pulumi-aws/sdk/go/aws/dynamodb"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/pulumi/pulumi/sdk/go/pulumi"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// DynamoAttribute represents an attribute for describing the key schema for the table and indexes.&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;DynamoAttribute&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// DynamoAttributes is an array of DynamoAttribute&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;DynamoAttributes&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;DynamoAttribute&lt;/span&gt;

&lt;span class="c"&gt;// ToList takes a DynamoAttributes object and turns that into a slice of map[string]interface{} so it can be correctly passed to the Pulumi runtime&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="n"&gt;DynamoAttributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;
        &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// GlobalSecondaryIndex represents the properties of a global secondary index&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;GlobalSecondaryIndex&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;HashKey&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;ProjectionType&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;WriteCapacity&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;ReadCapacity&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// GlobalSecondaryIndexes is an array of GlobalSecondaryIndex&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;GlobalSecondaryIndexes&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;GlobalSecondaryIndex&lt;/span&gt;

&lt;span class="c"&gt;// ToList takes a GlobalSecondaryIndexes object and turns that into a slice of map[string]interface{} so it can be correctly passed to the Pulumi runtime&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;GlobalSecondaryIndexes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"hash_key"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HashKey&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"projection_type"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProjectionType&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"write_capacity"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteCapacity&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"read_capacity"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadCapacity&lt;/span&gt;
        &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Create the attributes for ID and User&lt;/span&gt;
        &lt;span class="n"&gt;dynamoAttributes&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;DynamoAttributes&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;DynamoAttribute&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"S"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;DynamoAttribute&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"S"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;// Create a Global Secondary Index for the user field&lt;/span&gt;
        &lt;span class="n"&gt;gsi&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;GlobalSecondaryIndexes&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;GlobalSecondaryIndex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;HashKey&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;ProjectionType&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"ALL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;WriteCapacity&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;ReadCapacity&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;// Create a TableArgs struct that contains all the data&lt;/span&gt;
        &lt;span class="n"&gt;tableArgs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;dynamodb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TableArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Attributes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dynamoAttributes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;HashKey&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;WriteCapacity&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;ReadCapacity&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;GlobalSecondaryIndexes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;gsi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;// Let the Pulumi runtime create the table&lt;/span&gt;
        &lt;span class="n"&gt;userTable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;dynamodb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tableArgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;// Export the name of the newly created table as an output in the stack&lt;/span&gt;
        &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TableName"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userTable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pulumi up
&lt;/h2&gt;

&lt;p&gt;The last step is to add all of this to a new Pulumi project and run the &lt;code&gt;pulumi up&lt;/code&gt; command. To create a new, Go based, project, you can run the command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pulumi new go &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--name&lt;/span&gt; builder &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--description&lt;/span&gt; &lt;span class="s2"&gt;"An awesome Pulumi infrastructure-as-code Stack"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--stack&lt;/span&gt; retgits/builderstack

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can replace the code from the Go file with the code above and run &lt;code&gt;pulumi up&lt;/code&gt;. For a little more in-depth info on creating a new Pulumi project, check out one of my &lt;a href="https://retgits.com/2020/01/how-to-create-a-vpc-in-aws-using-pulumi-and-golang/"&gt;previous&lt;/a&gt; posts.&lt;/p&gt;

</description>
      <category>go</category>
      <category>devops</category>
    </item>
    <item>
      <title>How To Make Your AWS EKS Cluster Use Fargate Using Pulumi And Golang</title>
      <dc:creator>Leon Stigter</dc:creator>
      <pubDate>Thu, 16 Jan 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/retgits/how-to-make-your-aws-eks-cluster-use-fargate-using-pulumi-and-golang-4i65</link>
      <guid>https://forem.com/retgits/how-to-make-your-aws-eks-cluster-use-fargate-using-pulumi-and-golang-4i65</guid>
      <description>&lt;p&gt;At re:Invent, &lt;a href="https://aws.amazon.com/blogs/aws/amazon-eks-on-aws-fargate-now-generally-available/"&gt;AWS introduced the ability&lt;/a&gt; to have EKS run pods on AWS Fargate, and Fargate is &lt;a href="https://www.cloudjourney.io/articles/publiccloud/cost-matters-the-serverless-edition-ls/"&gt;cheaper than hosting Kubernetes yourself&lt;/a&gt;. In the last &lt;a href="https://retgits.com/2020/01/how-to-create-an-aws-eks-cluster-using-pulumi-and-golang/"&gt;post&lt;/a&gt; I created an EKS cluster, so let’s add this new capability to the cluster and remove the need to manage or provision infrastructure for our pods.&lt;/p&gt;

&lt;p&gt;The complete project is available on &lt;a href="https://github.com/retgits/pulumi-blogs/tree/fargate-blog"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;The minimum configuration for the Fargate profile is a name, the Kubenetes namespace it’ll work in, and the IAM role it needs to run the pods on AWS Fargate. The configuration below, which you can copy/paste into the YAML file from the previous blog, has three parameters. The parameter &lt;code&gt;fargate:profile-name&lt;/code&gt; is the name of the Fargate profile, the parameter &lt;code&gt;fargate:namespace&lt;/code&gt; is the Kubernetes namespace, and &lt;code&gt;fargate:execution-role-arn&lt;/code&gt; is the ARN of the IAM role. For more details on how to create the role, check out the &lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/pod-execution-role.html"&gt;AWS docs&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;fargate:profile-name: EKSFargateProfile&lt;/span&gt;
&lt;span class="s"&gt;fargate:namespace: example&lt;/span&gt;
&lt;span class="s"&gt;fargate:execution-role-arn: "arn:aws:iam::ACCOUNTID:role/EKSFargatePodExecutionRole"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can either use the command line, like &lt;code&gt;pulumi config set fargate:profile-name "EKSFargateProfile"&lt;/code&gt; to add these new configuration variables, or you can add them directly into the yaml file. The yaml file with all the configuration is called &lt;code&gt;Pulumi.&amp;lt;name of your project&amp;gt;.yaml&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding the Fargate profile
&lt;/h3&gt;

&lt;p&gt;The code below is an extension from the code created in the previous &lt;a href="https://retgits.com/2020/01/how-to-create-an-aws-eks-cluster-using-pulumi-and-golang/"&gt;post&lt;/a&gt;. So you can copy/paste this snippet into your Go code too. Walking through the code, it gets the name of the profile and the namespace from the YAML file. The &lt;code&gt;fargateProfileArgs&lt;/code&gt; the name of the &lt;a href="https://retgits.com/2020/01/how-to-create-an-aws-eks-cluster-using-pulumi-and-golang/"&gt;cluster&lt;/a&gt; and &lt;a href="https://retgits.com/2020/01/how-to-add-subnets-to-a-vpc-in-aws-using-pulumi-and-golang/"&gt;subnets&lt;/a&gt; from previous blog posts so check those out if you haven’t already. The call to &lt;code&gt;eks.NewFargateProfile()&lt;/code&gt; adds the Fargate profile to your EKS cluster.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Create an EKS Fargate Profile&lt;/span&gt;
&lt;span class="n"&gt;fargateProfileName&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"fargate:profile-name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;selectors&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;namespaces&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
&lt;span class="n"&gt;namespaces&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"fargate:namespace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;selectors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;namespaces&lt;/span&gt;

&lt;span class="n"&gt;fargateProfileArgs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;eks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FargateProfileArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ClusterName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;clusterName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;FargateProfileName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fargateProfileName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Tags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;SubnetIds&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;subnets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"subnet_ids"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;Selectors&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;selectors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;PodExecutionRoleArn&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"fargate:execution-role-arn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;fargateProfile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;eks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewFargateProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fargateProfileName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fargateProfileArgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"FARGATE-PROFILE-ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fargateProfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running the code
&lt;/h2&gt;

&lt;p&gt;Like the previous time, the last thing to do is run &lt;code&gt;pulumi up&lt;/code&gt; to tell Pulumi to go add the Fargate profile to your EKS cluster! If you’re using the same project and stack, Pulumi will automatically realize it needs to add the profile to the existing cluster and won’t create a new EKS cluster.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pulumi up
Previewing update &lt;span class="o"&gt;(&lt;/span&gt;builderstack&lt;span class="o"&gt;)&lt;/span&gt;:

     Type Name Plan       
     pulumi:pulumi:Stack builder-builderstack             
 + └─ aws:eks:FargateProfile EKSFargateProfile create     

Outputs:
  + FARGATE-PROFILE-ID: output&amp;lt;string&amp;gt;

Resources:
    + 1 to create
    5 unchanged

Do you want to perform this update? &lt;span class="nb"&gt;yes
&lt;/span&gt;Updating &lt;span class="o"&gt;(&lt;/span&gt;builderstack&lt;span class="o"&gt;)&lt;/span&gt;:

     Type Name Status      
     pulumi:pulumi:Stack builder-builderstack              
 + └─ aws:eks:FargateProfile EKSFargateProfile created     

Outputs:
    CLUSTER-ID : &lt;span class="s2"&gt;"myEKSCluster"&lt;/span&gt;
  + FARGATE-PROFILE-ID: &lt;span class="s2"&gt;"myEKSCluster:EKSFargateProfile"&lt;/span&gt;
    SUBNET-IDS : &lt;span class="o"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;[&lt;/span&gt;0]: &lt;span class="s2"&gt;"subnet-0a1909bec2e936bd7"&lt;/span&gt;
        &lt;span class="o"&gt;[&lt;/span&gt;1]: &lt;span class="s2"&gt;"subnet-09d229c2eb8061979"&lt;/span&gt;
    &lt;span class="o"&gt;]&lt;/span&gt;
    VPC-ID : &lt;span class="s2"&gt;"vpc-0437c750acf1050c3"&lt;/span&gt;

Resources:
    + 1 created
    5 unchanged

Duration: 2m27s

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

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dROpLoiq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://retgits.com/images/how-to-make-your-aws-eks-cluster-use-fargate-using-pulumi-and-golang-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dROpLoiq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://retgits.com/images/how-to-make-your-aws-eks-cluster-use-fargate-using-pulumi-and-golang-1.png" alt="The Pulumi console also has really useful links to the AWS console to see the resources." width="800" height="331"&gt;&lt;/a&gt;&lt;br&gt;
            &lt;p&gt;The Pulumi console also has really useful links to the AWS console to see the resources.&lt;/p&gt;

 &lt;/p&gt;

</description>
      <category>go</category>
      <category>devops</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>How To Create An AWS EKS Cluster Using Pulumi And Golang</title>
      <dc:creator>Leon Stigter</dc:creator>
      <pubDate>Tue, 14 Jan 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/retgits/how-to-create-an-aws-eks-cluster-using-pulumi-and-golang-2g5m</link>
      <guid>https://forem.com/retgits/how-to-create-an-aws-eks-cluster-using-pulumi-and-golang-2g5m</guid>
      <description>&lt;p&gt;Building a Kubernetes cluster is hard, so why not use a managed Kubernetes service? In the previous &lt;a href="https://retgits.com/2020/01/how-to-add-subnets-to-a-vpc-in-aws-using-pulumi-and-golang/"&gt;post&lt;/a&gt; I added subnets to a VPC. In this post, I’ll use the VPC to create an &lt;a href="https://aws.amazon.com/eks/"&gt;AWS EKS&lt;/a&gt; cluster.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The complete project is available on &lt;a href="https://github.com/retgits/pulumi-blogs/tree/eks-blog"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;The minimum configuration you need to create a cluster are a name for the cluster, the Kubernetes version you want to use, and an IAM role your cluster will use. While optional, specifying the types of logs your cluster will send to CloudWatch can be very useful when debugging and troubleshooting. The configuration below, which you can copy/paste into the YAML file from the previous blog, has four parameters. The parameter &lt;code&gt;eks:cluster-name&lt;/code&gt; is the name of the cluster. The parameter &lt;code&gt;eks:k8s-version&lt;/code&gt; is the version of Kubernetes to use (at the time of writing &lt;em&gt;1.14&lt;/em&gt; was the latest available version). The parameter &lt;code&gt;eks:cluster-role-arn&lt;/code&gt; has the ARN of the IAM role your cluster needs to perform tasks. For more details on how to create the role, check out the &lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/service_IAM_role.html"&gt;AWS docs&lt;/a&gt;. Lastly, the parameter &lt;code&gt;eks:cluster-log-types&lt;/code&gt; is a comma separated list of all the components that can emit logs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;eks:cluster-name: myEKSCluster&lt;/span&gt;
&lt;span class="s"&gt;eks:k8s-version: "1.14"&lt;/span&gt;
&lt;span class="s"&gt;eks:cluster-role-arn: "arn:aws:iam::ACCOUNTID:role/ServiceRoleForAmazonEKS"&lt;/span&gt;
&lt;span class="s"&gt;eks:cluster-log-types: "api,audit,authenticator,scheduler,controllerManager"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can either use the command line, like &lt;code&gt;pulumi config set eks:cluster-name "myEKSCluster"&lt;/code&gt; to add these new configuration variables, or you can add them directly into the yaml file. The yaml file with all the configuration is called &lt;code&gt;Pulumi.&amp;lt;name of your project&amp;gt;.yaml&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the cluster
&lt;/h2&gt;

&lt;p&gt;The code below is an extension from the code created in the previous &lt;a href="https://retgits.com/2020/01/how-to-add-subnets-to-a-vpc-in-aws-using-pulumi-and-golang/"&gt;post&lt;/a&gt;. So you can copy/paste this snippet into your Go code too. Walking through the code, it gets the configuration for the cluster name and enabled log types from the YAML file. It also uses the subnets created in the previous post. The call to &lt;code&gt;eks.NewCluster()&lt;/code&gt; will tell Pulumi to go create the EKS cluster in the VPC you have, using the subnets you already have created too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Create an EKS cluster&lt;/span&gt;
&lt;span class="n"&gt;clusterName&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"eks:cluster-name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;enabledClusterLogTypes&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"eks:cluster-log-types"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;","&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;clusterArgs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;eks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClusterArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;clusterName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"eks:k8s-version"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;RoleArn&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"eks:cluster-role-arn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;Tags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;VpcConfig&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;subnets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;EnabledClusterLogTypes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;enabledClusterLogTypes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;eks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewCluster&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clusterName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clusterArgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CLUSTER-ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cluster&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running the code
&lt;/h2&gt;

&lt;p&gt;Like the previous time, the last thing to do is run &lt;code&gt;pulumi up&lt;/code&gt; to tell Pulumi to go create an EKS cluster inside your VPC! If you’re using the same project and stack, Pulumi will automatically realize it needs to create the cluster inside the existing VPC and won’t create a new VPC. Running this code might take a little while for AWS to complete creating the cluster (in my case it took almost 10 minutes).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pulumi up
Previewing update &lt;span class="o"&gt;(&lt;/span&gt;builderstack&lt;span class="o"&gt;)&lt;/span&gt;:

     Type Name Plan       
     pulumi:pulumi:Stack builder-builderstack             
 + └─ aws:eks:Cluster myEKSCluster create     

Outputs:
  + CLUSTER-ID: output&amp;lt;string&amp;gt;

Resources:
    + 1 to create
    4 unchanged

Do you want to perform this update? &lt;span class="nb"&gt;yes
&lt;/span&gt;Updating &lt;span class="o"&gt;(&lt;/span&gt;builderstack&lt;span class="o"&gt;)&lt;/span&gt;:

     Type Name Status      
     pulumi:pulumi:Stack builder-builderstack              
 + └─ aws:eks:Cluster myEKSCluster created     

Outputs:
  + CLUSTER-ID: &lt;span class="s2"&gt;"myEKSCluster"&lt;/span&gt;
    SUBNET-IDS: &lt;span class="o"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;[&lt;/span&gt;0]: &lt;span class="s2"&gt;"subnet-&amp;lt;id&amp;gt;"&lt;/span&gt;
        &lt;span class="o"&gt;[&lt;/span&gt;1]: &lt;span class="s2"&gt;"subnet-&amp;lt;id&amp;gt;"&lt;/span&gt;
    &lt;span class="o"&gt;]&lt;/span&gt;
    VPC-ID : &lt;span class="s2"&gt;"vpc-&amp;lt;id&amp;gt;"&lt;/span&gt;

Resources:
    + 1 created
    4 unchanged

Duration: 9m55s

Permalink: https://app.pulumi.com/retgits/builder/builderstack/updates/3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3O2EtEpA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://retgits.com/images/how-to-create-an-aws-eks-cluster-using-pulumi-and-golang-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3O2EtEpA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://retgits.com/images/how-to-create-an-aws-eks-cluster-using-pulumi-and-golang-1.png" alt="The Pulumi console also has really useful links to the AWS console to see the resources." width="800" height="305"&gt;&lt;/a&gt;&lt;br&gt;
            &lt;p&gt;The Pulumi console also has really useful links to the AWS console to see the resources.&lt;/p&gt;

 &lt;/p&gt;

</description>
      <category>go</category>
      <category>devops</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>How To Add Subnets To a VPC In AWS Using Pulumi And Golang</title>
      <dc:creator>Leon Stigter</dc:creator>
      <pubDate>Thu, 09 Jan 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/retgits/how-to-add-subnets-to-a-vpc-in-aws-using-pulumi-and-golang-37kj</link>
      <guid>https://forem.com/retgits/how-to-add-subnets-to-a-vpc-in-aws-using-pulumi-and-golang-37kj</guid>
      <description>&lt;p&gt;In the previous &lt;a href="https://retgits.com/2020/01/how-to-create-a-vpc-in-aws-using-pulumi-and-golang/"&gt;post&lt;/a&gt;, I looked at &lt;a href="https://pulumi.com/"&gt;Pulumi&lt;/a&gt; to create a VPC. In this post, I’ll go over the steps to add some subnets to it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The complete project is available on &lt;a href="https://github.com/retgits/pulumi-blogs/tree/subnet-blog"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;A &lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html"&gt;subnet&lt;/a&gt; is a logical partition of your network, so in case of the subnets in a VPC, they’ll divide up the VPC into smaller chunks. A VPC spans all availability zones of a region, whereas a subnet is only inside a single availability zone. To make sure the app you run inside your VPC can move from one availability zone to another in case there is a failure, you’ll need to have at least two availability zones. Each of the zones also needs their own CIDR block. The configuration below, which you can copy/paste into the YAML file from the previous blog, has two parameters. The parameter &lt;code&gt;vpc:subnet-zones&lt;/code&gt; has a comma separated list of all the availability zones in which a subnet needs to be created. The parameter &lt;code&gt;vpc:subnet-ips&lt;/code&gt; has a comma separated list of the CIDR blocks for each of the subnets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;vpc:subnet-zones: "us-east-1a,us-east-1c"&lt;/span&gt;
&lt;span class="s"&gt;vpc:subnet-ips: "172.32.32.0/20,172.32.80.0/20"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can either use the command line, like &lt;code&gt;pulumi config set vpc:subnet-zones "us-east-1a,us-east-1c"&lt;/code&gt; to add these new configuration variables, or you can add them directly into the yaml file. The yaml file with all the configuration is called &lt;code&gt;Pulumi.&amp;lt;name of your project&amp;gt;.yaml&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating subnets
&lt;/h2&gt;

&lt;p&gt;The code below is an extension from the code created in the previous &lt;a href="https://retgits.com/2020/01/how-to-create-a-vpc-in-aws-using-pulumi-and-golang/"&gt;post&lt;/a&gt;. So you can copy/paste this snippet into your Go code too. Walking through the code, it gets the configuration for zones (&lt;code&gt;subnetZones&lt;/code&gt;) and CIDR blocks (&lt;code&gt;subnetIPs&lt;/code&gt;) from the YAML file. The code reads the variable and splits it on the comma delimiter. For each of the zones it’ll create a new subnet inside the VPC (see &lt;code&gt;subnetArgs&lt;/code&gt;) and give it a name based on the name of the VPC. The last step in the &lt;code&gt;range&lt;/code&gt; loop is to add the new ID to an array of subnets to export to the Pulumi console.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Create the required number of subnets&lt;/span&gt;
&lt;span class="n"&gt;subnets&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
&lt;span class="n"&gt;subnets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"subnet_ids"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;subnetZones&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"vpc:subnet-zones"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;","&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;subnetIPs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"vpc:subnet-ips"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;","&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;availabilityZone&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;subnetZones&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;subnetArgs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ec2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SubnetArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Tags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;VpcId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;vpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;CidrBlock&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;subnetIPs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;AvailabilityZone&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;availabilityZone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;subnet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ec2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewSubnet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s-subnet-%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vpcName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;subnetArgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;subnets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"subnet_ids"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subnets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"subnet_ids"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}),&lt;/span&gt; &lt;span class="n"&gt;subnet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SUBNET-IDS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subnets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"subnet_ids"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running the code
&lt;/h2&gt;

&lt;p&gt;Like the previous time, the last thing to do is run &lt;code&gt;pulumi up&lt;/code&gt; to tell Pulumi to go add subnets to your VPC! If you’re using the same project and stack, Pulumi will automatically realize it needs to add subnets to the existing VPC and won’t create a new VPC.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pulumi up
Previewing update &lt;span class="o"&gt;(&lt;/span&gt;builderstack&lt;span class="o"&gt;)&lt;/span&gt;:

     Type Name Plan       
     pulumi:pulumi:Stack builder-builderstack             
 + ├─ aws:ec2:Subnet myPulumiVPC-subnet-1 create     
 + └─ aws:ec2:Subnet myPulumiVPC-subnet-0 create     

Outputs:
  + SUBNET-IDS: &lt;span class="o"&gt;[&lt;/span&gt;
  + &lt;span class="o"&gt;[&lt;/span&gt;0]: output&amp;lt;string&amp;gt;
  + &lt;span class="o"&gt;[&lt;/span&gt;1]: output&amp;lt;string&amp;gt;
    &lt;span class="o"&gt;]&lt;/span&gt;

Resources:
    + 2 to create
    2 unchanged

Do you want to perform this update? &lt;span class="nb"&gt;yes
&lt;/span&gt;Updating &lt;span class="o"&gt;(&lt;/span&gt;builderstack&lt;span class="o"&gt;)&lt;/span&gt;:

     Type Name Status      
     pulumi:pulumi:Stack builder-builderstack              
 + ├─ aws:ec2:Subnet myPulumiVPC-subnet-1 created     
 + └─ aws:ec2:Subnet myPulumiVPC-subnet-0 created     

Outputs:
  + SUBNET-IDS: &lt;span class="o"&gt;[&lt;/span&gt;
  + &lt;span class="o"&gt;[&lt;/span&gt;0]: &lt;span class="s2"&gt;"subnet-&amp;lt;id&amp;gt;"&lt;/span&gt;
  + &lt;span class="o"&gt;[&lt;/span&gt;1]: &lt;span class="s2"&gt;"subnet-&amp;lt;id&amp;gt;"&lt;/span&gt;
    &lt;span class="o"&gt;]&lt;/span&gt;
    VPC-ID : &lt;span class="s2"&gt;"vpc-&amp;lt;id&amp;gt;"&lt;/span&gt;

Resources:
    + 2 created
    2 unchanged

Duration: 8s

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

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Tm2gjMBG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://retgits.com/images/how-to-add-subnets-to-a-vpc-in-aws-using-pulumi-and-golang-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Tm2gjMBG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://retgits.com/images/how-to-add-subnets-to-a-vpc-in-aws-using-pulumi-and-golang-1.png" alt="The Pulumi console also has really useful links to the AWS console to see the resources." width="800" height="278"&gt;&lt;/a&gt;&lt;br&gt;
            &lt;p&gt;The Pulumi console also has really useful links to the AWS console to see the resources.&lt;/p&gt;

 &lt;/p&gt;

</description>
      <category>go</category>
      <category>devops</category>
    </item>
    <item>
      <title>How To Create a VPC In AWS Using Pulumi And Golang</title>
      <dc:creator>Leon Stigter</dc:creator>
      <pubDate>Tue, 07 Jan 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/retgits/how-to-create-a-vpc-in-aws-using-pulumi-and-golang-3ncp</link>
      <guid>https://forem.com/retgits/how-to-create-a-vpc-in-aws-using-pulumi-and-golang-3ncp</guid>
      <description>&lt;p&gt;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 &lt;a href="https://pulumi.com"&gt;Pulumi&lt;/a&gt; allows you to do!&lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://github.com/retgits/pulumi-blogs/tree/vpc-blog"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A new project
&lt;/h2&gt;

&lt;p&gt;If you haven’t done so already, you might want to take a quick second and head over to the &lt;a href="https://app.pulumi.com/signin"&gt;Pulumi website&lt;/a&gt; to create a new account. It’s free forever for personal use! Once you’ve done that and installed the &lt;a href="https://www.pulumi.com/docs/get-started/aws/install-pulumi/"&gt;CLI&lt;/a&gt; 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 (&lt;code&gt;go&lt;/code&gt; in this case). You’ll be able to specify the project name (with the &lt;code&gt;--name&lt;/code&gt; flag), the description (with the &lt;code&gt;--description&lt;/code&gt; flag), and the stack name (with the &lt;code&gt;--stack&lt;/code&gt; flag).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pulumi new go &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--name&lt;/span&gt; builder &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--description&lt;/span&gt; &lt;span class="s2"&gt;"An awesome Pulumi infrastructure-as-code Stack"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--stack&lt;/span&gt; retgits/builderstack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, I’ve used the project name &lt;code&gt;builder&lt;/code&gt; and the stack is called &lt;code&gt;retgits/builderstack&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Go modules
&lt;/h2&gt;

&lt;p&gt;The current Go template still relies on &lt;code&gt;dep&lt;/code&gt; for dependency management, but with the introduction of Go modules you probably want to use that to manage dependencies. Luckily, switching from &lt;code&gt;dep&lt;/code&gt; to &lt;code&gt;Go modules&lt;/code&gt; only requires three commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go mod init github.com/retgits/builder
go mod tidy
&lt;span class="nb"&gt;rm &lt;/span&gt;Gopkg.&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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 &lt;code&gt;github.com/retgits/builder&lt;/code&gt;. The second command takes the input from &lt;code&gt;Gopkg.toml&lt;/code&gt; and creates entries in &lt;code&gt;go.mod&lt;/code&gt; for each entry. The third command removes the &lt;code&gt;Gopkg&lt;/code&gt; files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Default configuration variables
&lt;/h2&gt;

&lt;p&gt;To ultimate deploy to AWS, Pulumi needs to know how to connect to AWS. To connect, Pulumi uses a &lt;em&gt;provider&lt;/em&gt; (more on that later). The configuration for that provider can be set through the command line: &lt;code&gt;pulumi config set aws:&amp;lt;option&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;pulumi config set aws:profile default&lt;/span&gt;
&lt;span class="s"&gt;pulumi config set aws:region us-east-1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h2&gt;
  
  
  Adding more configuration variables
&lt;/h2&gt;

&lt;p&gt;As a &lt;a href="https://aws.amazon.com/answers/account-management/aws-tagging-strategies/"&gt;best practice&lt;/a&gt;, 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 &lt;em&gt;version&lt;/em&gt; (because infrastructure-as-code makes it easy to version your infrastructure too), &lt;em&gt;author&lt;/em&gt; (so you can see who did the deployment), &lt;em&gt;team&lt;/em&gt; (so you can see which team did a deployment), and &lt;em&gt;feature&lt;/em&gt; (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.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;tags:version: "0.1.0"&lt;/span&gt;
&lt;span class="s"&gt;tags:author: &amp;lt;your name&amp;gt;&lt;/span&gt;
&lt;span class="s"&gt;tags:team: &amp;lt;your team&amp;gt;&lt;/span&gt;
&lt;span class="s"&gt;tags:feature: myFirstVPCWithPulumi&lt;/span&gt;
&lt;span class="s"&gt;vpc:name: myPulumiVPC&lt;/span&gt;
&lt;span class="s"&gt;vpc:cidr-block: "172.32.0.0/16"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are two ways you can add configuration variables to your Pulumi config. You can either use the command line, like &lt;code&gt;pulumi config set tags:version "0.1.0"&lt;/code&gt;, or you can add them directly into the yaml file. The yaml file with all the configuration is called &lt;code&gt;Pulumi.&amp;lt;name of your project&amp;gt;.yaml&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using configuration variables in your code
&lt;/h2&gt;

&lt;p&gt;The configuration variables that you’ve added to the YAML file are accessible through the &lt;code&gt;pulumi.Context&lt;/code&gt; object. You can use the &lt;code&gt;GetConfig()&lt;/code&gt; 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.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// getEnv searches for the requested key in the pulumi context and provides either the value of the key or the fallback.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fallback&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fallback&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Making it all work
&lt;/h2&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Prepare the tags that are used for each individual resource so they can be found&lt;/span&gt;
        &lt;span class="c"&gt;// using the Resource Groups service in the AWS Console&lt;/span&gt;
        &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
        &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"tags:version"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"tags:author"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"team"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"tags:team"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"feature"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"tags:feature"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"region"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"aws:region"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c"&gt;// Create a VPC for the EKS cluster&lt;/span&gt;
        &lt;span class="n"&gt;cidrBlock&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"vpc:cidr-block"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;vpcArgs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ec2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VpcArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;CidrBlock&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cidrBlock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Tags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;vpcName&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"vpc:name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;vpc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ec2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewVpc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vpcName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vpcArgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;// Export IDs of the created resources to the Pulumi stack&lt;/span&gt;
        &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"VPC-ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running the code
&lt;/h2&gt;

&lt;p&gt;While most other languages rely on the package manager of the language to install Pulumi plugins (also called &lt;em&gt;providers&lt;/em&gt;), 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.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pulumi plugin &lt;span class="nb"&gt;install &lt;/span&gt;resource aws v1.17.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last thing to do is run &lt;code&gt;pulumi up&lt;/code&gt; to tell Pulumi to go create your VPC!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pulumi up
Previewing update &lt;span class="o"&gt;(&lt;/span&gt;builderstack&lt;span class="o"&gt;)&lt;/span&gt;:

     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? &lt;span class="nb"&gt;yes
&lt;/span&gt;Updating &lt;span class="o"&gt;(&lt;/span&gt;builderstack&lt;span class="o"&gt;)&lt;/span&gt;:

     Type Name Status      
 + pulumi:pulumi:Stack builder-builderstack created     
 + └─ aws:ec2:Vpc myPulumiVPC created     

Outputs:
    VPC-ID: &lt;span class="s2"&gt;"vpc-&amp;lt;id&amp;gt;"&lt;/span&gt;

Resources:
    + 2 created

Duration: 11s

Permalink: https://app.pulumi.com/retgits/builder/builderstack/updates/1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eg_feusq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://retgits.com/images/how-to-create-a-vpc-in-aws-using-pulumi-and-golang-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eg_feusq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://retgits.com/images/how-to-create-a-vpc-in-aws-using-pulumi-and-golang-1.png" alt="The Pulumi console also has really useful links to the AWS console to see the resources." width="800" height="225"&gt;&lt;/a&gt;&lt;br&gt;
            &lt;p&gt;The Pulumi console also has really useful links to the AWS console to see the resources.&lt;/p&gt;

 &lt;/p&gt;

</description>
      <category>go</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
