Using ChatGPT for IaC (infrastructure as code)

Using ChatGPT for IaC (infrastructure as code)

Festus Obi on 20-02-2023 | 10 min read

If you're working in the tech industry, you most definitely have seen a lot of posts on social media about ChatGPT. This is being talked about a lot. Like every new & shiny tool that gets published, ChatGPT is generating a lot of buzz.

Many software developers are already using it to generate code of different types, from small functions in a particular language to even a full-blown website/application. The questions that come to mind are:

  • is ChatGPT really worth the hype?
  • what can it be used for?
  • How can you use it for your job?
  • is ChatGPT strictly for software developers?
  • how can ChatGPT be used in DevOps, systems administration, or platform engineering?

If you work in DevOps or any other field that does not involve building software, most likely you don’t write code for the actual product but enable people who do, to get this done with ease and generally make the product lifecycle get automated as much as possible. This means working on deployment pipelines, continuous integration, and infrastructure as code for provisioning different kinds of resources like eks cluster, amazon elastic compute cloud, monitoring production software, etc.

For today’s post, we will focus on using ChatGPT for one of the DevOps-related tasks - infrastructure as code. We will be testing ChatGPT’s knowledge of cloud infrastructures and also see how accurate ChatGPT will be.

Before we get our hands dirty, let’s actually get to know - what exactly is ChatGPT?

What is ChatGPT

ChatGPT is a trained AI model that you can interact with in a conversational manner. Put, you ask a question, and chatgpt answers you. If you haven’t had a chance to check this out, for clarity’s sake, let’s imagine you want to generate a golang function for a Fibonacci sequence, the response I got from chatgpt after tasking it to do so is the italicized explanations & code snippet below:

Here is an example of a Golang function that generates the Fibonacci sequence up to a given number of elements:

package main

import "fmt"

func fibonacci(n int) []int {
    fibSeq := make([]int, n)
    fibSeq[0] = 0
    fibSeq[1] = 1

    for i := 2; i < n; i++ {
        fibSeq[i] = fibSeq[i-1] + fibSeq[i-2]
    }

    return fibSeq
}

func main() {
    n := 10
    fmt.Println(fibonacci(n))
}

In this example, the function Fibonacci takes an integer argument n which represents the number of elements in the desired Fibonacci sequence. The function returns a slice of integers representing the Fibonacci sequence.

The function first creates a slice fibSeq of length n and sets the first two elements of the sequence to 0 and 1, respectively. The for loop then iteratively calculates and stores the next elements of the sequence by adding the previous two elements.

Finally, the function returns the complete Fibonacci sequence as a slice of integers.

Scenarios

  1. Generate Iac template (CloudFormation & Terraform).
  2. Convert terraform code to another IaC tool (CloudFormation to Terraform, Terraform to Terragrunt, Terraform to Pulumi).
  3. Convert the IaC template to another provider (AWS to Azure).

Prerequisites

  1. ChatGPT setup - if you have not set up a personal account and would like to do so, click here.
  2. Code Editor - we need a code editor to test the generated templates for the use cases. I recommend VS Code since it has extensions for most providers and tools.
  3. Terminal - Needed to run commands for each tool.
  4. CLI’s - AWS CLI, Azure CLI, Pulumi CLI, etc.

    if you can see a window that looks like the image below, you are good to go with ChatGPT

    As you can see from the above image, there are already clues regarding examples, capabilities, and limitations of ChatGPT. The text bar at the bottom is where you input your question and once you send it, the rest of the magic happens within a short time.

Generate IaC templates

In order to get a hang of how ChatGPT actually works, let’s try out our first scenario.

CloudFormation EC2 template

I have never worked with CloudFormation before; for me, this is something I found an added value. The fact is that instead of spending time learning CloudFormation in full, I can just generate the code for the little bits that I need CloudFormation for. So I asked ChatGPT the questions below.

generate a CloudFormation template to create an EC2

after a few seconds, ChatGPT generated the reply in the image below.

if you are familiar with YAML and have knowledge of the cloud & cloud services it provides, you can easily tell that while this is super cool, it isn’t exactly what you would simply paste in your code editor and provision on a production environment.

I have no experience with CloudFormation but I can see that the code will create a security group and enable ssh from anywhere which is not something you would generally do in production. Again, if we want to host a web app or use this instance as a web server, we certainly need to set up ingress rules for HTTP/HTTPS for the security group.

The response you get from ChatGPT really depends on how well your needs are explained to chatgpt. Now let’s repeat something well-detailed and also test it out. Since Terraform is multi-cloud and enables us to achieve other use cases, I will be switching to Terraform.

Terraform EC2 template

So far we have tried ChatGPT’s capability in writing infrastructure code and it works. We just need to properly explain our use case and ChatGPT would be able to generate the proper Terraform template. I have tasked ChatGPT by entering the sentences italicized below :

Write a Terraform template to create the following:

  1. A VPC with a CIDR block of 10.2.0.0/16 in the region eu-central-1 and name it test_vpc.
  2. A subnet with a CIDR block of 10.2.0.0/24, associated with the VPC and with no public IPs enabled and name it test_subnet.
  3. A security group that allows ingress on ports 22, 80, and 443 from CIDR block 10.2.0.0/16 and name it test_security_group.
  4. An EC2 instance of type = t2.micro, imageId = ami-06c39ed6b42908a36, associated with the specified subnet and using the specified security group and without the key.

As expected, ChatGPT replies with the terraform template and a brief explanation of the code/what needs to be changed before the code can be used. The code generated is below and the explanation is the italicized text below the code snippet.

provider "aws" {
  region = "eu-central-1"
}

resource "aws_vpc" "test_vpc" {
  cidr_block = "10.2.0.0/16"
  name       = "test_vpc"
}

resource "aws_subnet" "test_subnet" {
  cidr_block = "10.2.0.0/24"
  vpc_id     = aws_vpc.test_vpc.id
  map_public_ip_on_launch = false
  name       = "test_subnet"
}

resource "aws_security_group" "test_security_group" {
  name        = "test_security_group"
  description = "Allow SSH and HTTP/HTTPS traffic"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["10.2.0.0/16"]
  }

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["10.2.0.0/16"]
  }

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["10.2.0.0/16"]
  }
}

resource "aws_instance" "example_instance" {
  ami           = "ami-06c39ed6b42908a36"
  instance_type = "t2.micro"
  subnet_id     = aws_subnet.test_subnet.id
  vpc_security_group_ids = [aws_security_group.test_security_group.id]
}
  • In this example, the AWS provider is configured to use the eu-central-1 region.
  • The aws_vpc resource creates the VPC with a CIDR block of 10.2.0.0/16 and the name test_vpc.
  • The aws_subnet resource creates a subnet with a CIDR block of 10.2.0.0/24 associated with the VPC and with no public IPs enabled and the name test_subnet.
  • The aws_security_group resource creates a security group that allows incoming traffic on ports 22, 80, and 443 from the 10.2.0.0/16 CIDR block and the name test_security_group.
  • Finally, the aws_instance resource creates an EC2 instance of type t2.micro, using the specified AMI ID, associated with the subnet, using the security group, and without a key.

If we compare the Terraform template above with the previously generated template for CloudFormation, we can see there is a lot happening now. This is expected, we have not only tasked ChatGPT to generate an EC2 instance, but we were also more detailed and specific in what components we need and some preferred config like names, CIDR/IP address e.t.c

Now, let’s run this and see if it works without us making any manual changes. At this point, I assume you have already set up aws cli setup.

I have created a directory with the name chatgpt-for-iac and created a file with the name main.tf. Open your code editor and paste the code generated by chatgpt into main.tf file.

Now we have everything we need to see if the code does what we want. The first thing we need to do is to initialize Terraform backend and provider plugins and then we run the plan to see what the code will do.

> terraform init
> terraform plan

I have run the plan and of course, it fails. Truth is, I expected it to fail. There are so many reasons why that is so. I’m not sure what terraform version was generated as the code did not have any version specified and I am also not sure if this matches the version on my machine. In my case, the error I got is below:

If you are familiar with Terraform, you can already tell that the name argument is not even necessary since the name of the resource is already specified at the top before the open curly bracket. The issue also exists in the vpc resource part. We can fix the error by removing the name attribute from both the vpc resource block and the subnet resource block. The final version of the code should look like the below just like the below code:

resource "aws_vpc" "test_vpc" {
  cidr_block = "10.2.0.0/16"
}

resource "aws_subnet" "test_subnet" {
  cidr_block              = "10.2.0.0/24"
  vpc_id                  = aws_vpc.test_vpc.id
  map_public_ip_on_launch = false
}

Now let’s rerun the plan and see if everything else is fine. In my case, it does seem that everything is fine because my Terraform plan command succeeded and I can see all the resources that our code will create. It is pretty normal for the plan to succeed and the apply fail so I would not rejoice just yet until we run apply. The command is below:

> terraform apply

I would not say I expected it did fail and I can see the error below:

After looking at the code, I can see what the issue is, no vpc_id was provided in the security group resource block. Add the below under the description of the security group.

vpc_id = aws_vpc.test_vpc.id

Rerun Terraform plan. This will show what Terraform would change. It should be almost the same as the previous plan but we already ran apply so some resources were already created. If all goes fine with the plan, you can re-run the apply command.

My Terraform apply ran successfully this time and our infra should be up and running. You can verify this by checking AWS console.

As you can see, we only needed to delete two lines and add one line. This small minor edit could have been easily avoided and ChatGPT’s response could have worked perfectly if we explained better to ChatGPT.

Now, let’s try out a different scenario.

Convert terraform code to another IaC tool

Imagine you have previously written your infra code with Terraform and then you discovered that Terragrunt is better. Now you need to rewrite your code. It might be easy to rewrite one file with 50 lines but what if you have over 40 files and millions of lines?

Convert terraform code to terragrunt using chatgpt

I tried to convert the contents of our main.tf file to Terragrunt like the below:

The image above was cropped, to try it out yourself, simply type the first sentence followed by a blank space and then paste the contents of the main.tf file which has the same code we edited previously.

Below is a cropped image of ChatGPT’s response:

This is definitely not going to work if we try, for so many reasons but the most obvious one is that our terraform resource blocks have been converted to modules in Terragrunt even though we are not trying to create modules. Getting this will require you to know Terragrunt and to be honest, in this case, you’re better off writing it from scratch or explaining your existing Terraform infra, while chatgpt generates the terragrunt code from scratch.

Convert Terraform code to Pulumi using ChatGPT

What if we already have a Terraform code and we wanted to generate a Pulumi code to match it?

Again, I repeated the step tried previously. Except, this time instead of tasking chatgpt to convert the terraform template to terragrunt, I specified Pulumi and ChatGPT responded with the code below:

import * as aws from "@pulumi/aws";

const region = "eu-central-1";

const testVpc = new aws.ec2.Vpc("test_vpc", {
    cidrBlock: "10.2.0.0/16",
});

const testSubnet = new aws.ec2.Subnet("test_subnet", {
    cidrBlock: "10.2.0.0/24",
    vpcId: testVpc.id,
    mapPublicIpOnLaunch: false,
});

const testSecurityGroup = new aws.ec2.SecurityGroup("test_security_group", {
    name: "test_security_group",
    description: "Allow SSH and HTTP/HTTPS traffic",
    vpcId: testVpc.id,
    ingress: [
        {
            fromPort: 22,
            toPort: 22,
            protocol: "tcp",
            cidrBlocks: ["10.2.0.0/16"],
        },
        {
            fromPort: 80,
            toPort: 80,
            protocol: "tcp",
            cidrBlocks: ["10.2.0.0/16"],
        },
        {
            fromPort: 443,
            toPort: 443,
            protocol: "tcp",
            cidrBlocks: ["10.2.0.0/16"],
        },
    ],
});

const exampleInstance = new aws.ec2.Instance("example_instance", {
    ami: "ami-06c39ed6b42908a36",
    instanceType: "t2.micro",
    subnetId: testSubnet.id,
    vpcSecurityGroupIds: [testSecurityGroup.id],
});

If you have worked with Pulumi before for provisioning cloud services, you should know that with Pulumi, IaC is written using programming languages (Typescript, Python, Go, C#, Java) and even YAML. If you look closely, you’ll notice that the default template that chatGPT generated uses typescript. Of course, we can change this by asking it to generate one using Go.

Let’s test out the code. Unlike Terraform which simply requires creating just one file, to repeat the same thing using Pulumi requires a few more steps. Since this is not a Pulumi tutorial, I will skip the initial setup and just help us test the code above. When I run the equivalent of Terraform plan (pulumi up), I see the below:

I selected yes so we can see if this code works fine and in this case, I am really impressed. If you are trying it out like me, remember to destroy the resources created with Terraform earlier. Since the code is the same but with a different tool, it will still throw errors because the names of the resources are still the same and when Pulumi tries to create them, it will get a response that the resources with those names already exist.

All resources were provisioned with no errors and no manual change was required.

Let’s try out the last scenario.

convert IaC template to another provider

So far, we have been working with different IaC tools but within AWS Cloud Provider. But what if we want to rewrite our code to match what can be used to provision resources on azure or gcp while still using terraform? I am going to use the same Terraform code we have been using. I asked chatGPT the question below:

The only thing different between the above and previous scenario is the first/topmost line. The code that is below is the same terraform code. ChatGPT’s response is the code below:

provider "azurerm" {
version = "2.32.0"
features {}
}

resource "azurerm_resource_group" "test_rg" {
name = "test_rg"
location = "West Europe"
}

resource "azurerm_virtual_network" "test_vnet" {
name = "test_vnet"
address_space = ["10.2.0.0/16"]
location = azurerm_resource_group.test_rg.location
resource_group_name = azurerm_resource_group.test_rg.name
}

resource "azurerm_subnet" "test_subnet" {
name = "test_subnet"
resource_group_name = azurerm_resource_group.test_rg.name
virtual_network_name = azurerm_virtual_network.test_vnet.name
address_prefix = "10.2.0.0/24"
}

resource "azurerm_network_security_group" "test_nsg" {
name = "test_nsg"
location = azurerm_resource_group.test_rg.location
resource_group_name = azurerm_resource_group.test_rg.name

security_rule {
name = "allow_ssh"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = ""
destination_port_range = "22"
source_address_prefix = "10.2.0.0/16"
destination_address_prefix = ""
}

security_rule {
name = "allow_http"
priority = 101
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = ""
destination_port_range = "80"
source_address_prefix = "10.2.0.0/16"
destination_address_prefix = ""
}

security_rule {
name = "allow_https"
priority = 102
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = ""
destination_port_range = "443"
source_address_prefix = "10.2.0.0/16"
destination_address_prefix = ""
}
}

resource "azurerm_network_interface" "test_nic" {
name = "test_nic"
location = azurerm_resource_group.test_rg.location
resource_group_name = azurerm_resource_group.test_rg.name
network_security_group_id = azurerm_network_security_group.test_nsg.id
subnet_id = azurerm_subnet.test_subnet.id

I won’t be testing this but by looking at the code above, I must say that it is quite impressive. I can see three security rules that match what we had in Terraform, the region switches to West Europe which is not Germany like the aws region (eu-central-1) even though there is an Azure region in Germany. It also tried to append the prefix test to the services even though they have different names when compared to AWS but it did know that the word test should be used as a prefix.

Should you use ChatGPT for your IaC project?

I have worked on just a few examples and while I did spend time writing plain texts to explain my need to ChatGPT and manual editing of the generated terraform template, I would have spent much more if I had to write them myself.

I guess you can copy from your old projects and reuse the codes that match what you need but the various scenarios above show that there might be much more complicated use cases that ChatGPT can help you on. In my case, I have never worked with Pulumi before today but I was able to provision resources with Pulumi in less than 5 minutes.

chatGPT Infrastructureascode IaC demoproject