1. Docs
  2. Pulumi IaC
  3. Get started
  4. Pulumi for Terraform Users
  5. First Look - Terraform HCL vs Pulumi Programs

First Look - Terraform HCL vs Pulumi Programs

    Let’s try creating the same resources using both Terraform HCL and a Pulumi program. This basic example will also serve to verify your cloud connectivity.

    The Terraform way of doing things

    In Terraform, if you wanted to query an AMI ID you might write something like this in Hashicorp Configuration Language (HCL):

    data "aws_ami" "ubuntu" {
      region      = "us-west-2"
      most_recent = true
      owners      = ["099720109477"] # Canonical
    
      filter {
        name   = "name"
        values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
      }
    }
    
    output "latest_ubuntu_ami_id" {
      value = data.aws_ami.ubuntu.id
    }
    
    output "latest_ubuntu_ami_name" {
      value = data.aws_ami.ubuntu.name
    }
    

    If you run this Terraform config, you should see output showing the latest Ubuntu AMI information. However, it’s important to note that HCL is not a programming language. It is a configuration language, similar to YAML or JSON, with a bit more expressiveness and modularization capabilities. In Pulumi, you use general purpose programming languages to express your desired state of your cloud resources, in the context of a Pulumi program.

    Pulumi programs

    Let’s try creating the same resources in a Pulumi program. The key difference between Terraform and Pulumi is that Pulumi allows you to use your preferred programming language instead of HCL. Both approaches query the same AWS API and return identical results:

    First, create a new Pulumi program:

    $ mkdir pulumi-terraform-test && cd pulumi-terraform-test
    $ pulumi new aws-typescript --yes
    

    Replace the contents of index.ts with:

    import * as aws from "@pulumi/aws";
    
    // Query existing Ubuntu AMIs (read-only operation)
    const ubuntu = aws.ec2.getAmiOutput({
        region: "us-west-2",
        mostRecent: true,
        owners: ["099720109477"], // Canonical
        filters: [
            {
                name: "name",
                values: ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"],
            },
        ],
    });
    
    export const latestUbuntuAmiId = ubuntu.id;
    export const latestUbuntuAmiName = ubuntu.name;
    

    First, create a new Pulumi program:

    $ mkdir pulumi-terraform-test && cd pulumi-terraform-test
    $ pulumi new aws-python --yes
    

    Replace the contents of __main__.py with:

    import pulumi
    import pulumi_aws as aws
    
    # Query existing Ubuntu AMIs (read-only operation)
    ubuntu = aws.ec2.get_ami(
        region="us-west-2",
        most_recent=True,
        owners=["099720109477"],  # Canonical
        filters=[
            {
                "name": "name",
                "values": ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"],
            }
        ],
    )
    
    pulumi.export("latestUbuntuAmiId", ubuntu.id)
    pulumi.export("latestUbuntuAmiName", ubuntu.name)
    

    First, create a new Pulumi program:

    $ mkdir pulumi-terraform-test && cd pulumi-terraform-test
    $ pulumi new aws-go --yes
    

    Replace the contents of main.go with:

    package main
    
    import (
    	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
    	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
    )
    
    func main() {
    	pulumi.Run(func(ctx *pulumi.Context) error {
    		// Query existing Ubuntu AMIs (read-only operation)
    		ubuntu, err := ec2.LookupAmi(ctx, &ec2.LookupAmiArgs{
                Region: pulumi.StringRef("us-west-2"),
    			MostRecent: pulumi.BoolRef(true),
    			Owners:     []string{"099720109477"}, // Canonical
    			Filters: []ec2.GetAmiFilter{
    				{
    					Name:   "name",
    					Values: []string{"ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"},
    				},
    			},
    		})
    		if err != nil {
    			return err
    		}
    
    		ctx.Export("latestUbuntuAmiId", pulumi.String(ubuntu.Id))
    		ctx.Export("latestUbuntuAmiName", pulumi.String(ubuntu.Name))
    		return nil
    	})
    }
    

    First, create a new Pulumi program:

    $ mkdir pulumi-terraform-test && cd pulumi-terraform-test
    $ pulumi new aws-csharp --yes
    

    Replace the contents of Program.cs with:

    using System.Collections.Generic;
    using Pulumi;
    using Pulumi.Aws.Ec2;
    using Pulumi.Aws.Ec2.Inputs;
    
    return await Deployment.RunAsync(() =>
    {
        // Query existing Ubuntu AMIs (read-only operation)
        var ubuntu = GetAmi.Invoke(new()
        {
            Region = "us-west-2",
            MostRecent = true,
            Owners = new[] { "099720109477" }, // Canonical
            Filters = new[]
            {
                new GetAmiFilterInputArgs
                {
                    Name = "name",
                    Values = new[] { "ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*" },
                },
            },
        });
    
        return new Dictionary<string, object?>
        {
            ["latestUbuntuAmiId"] = ubuntu.Apply(ubuntu => ubuntu.Id),
            ["latestUbuntuAmiName"] = ubuntu.Apply(ubuntu => ubuntu.Name),
        };
    });
    

    First, create a new Pulumi program:

    $ mkdir pulumi-terraform-test && cd pulumi-terraform-test
    $ pulumi new aws-java --yes
    

    Replace the contents of src/main/java/myproject/App.java with:

    package myproject;
    
    import com.pulumi.Pulumi;
    import com.pulumi.aws.ec2.Ec2Functions;
    import com.pulumi.aws.ec2.inputs.GetAmiArgs;
    import com.pulumi.aws.ec2.inputs.GetAmiFilterArgs;
    import com.pulumi.core.Output;
    
    import java.util.List;
    
    public class App {
        public static void main(String[] args) {
            Pulumi.run(ctx -> {
                // Query existing Ubuntu AMIs (read-only operation)
                var ubuntu = Ec2Functions.getAmi(GetAmiArgs.builder()
                    .region("us-west-2")
                    .mostRecent(true)
                    .owners("099720109477") // Canonical
                    .filters(GetAmiFilterArgs.builder()
                        .name("name")
                        .values("ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*")
                        .build())
                    .build());
    
                ctx.export("latestUbuntuAmiId", ubuntu.applyValue(ami -> ami.id()));
                ctx.export("latestUbuntuAmiName", ubuntu.applyValue(ami -> ami.name()));
            });
        }
    }
    

    First, create a new Pulumi program:

    $ mkdir pulumi-terraform-test && cd pulumi-terraform-test
    $ pulumi new aws-yaml --yes
    

    Replace the contents of Pulumi.yaml with:

    name: pulumi-terraform-test
    runtime: yaml
    description: Test Pulumi and AWS connectivity
    
    variables:
      ubuntu:
        fn::invoke:
          function: aws:ec2:getAmi
          arguments:
            region: us-west-2
            mostRecent: true
            owners: ["099720109477"] # Canonical
            filters:
              - name: name
                values: ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
    
    outputs:
      latestUbuntuAmiId: ${ubuntu.id}
      latestUbuntuAmiName: ${ubuntu.name}
    

    Run the test:

    $ pulumi up
    

    You should see output showing the latest Ubuntu AMI information, confirming that Pulumi can successfully query your AWS environment.

    Clean up

    Remove the test resources:

    $ pulumi destroy --yes
    $ pulumi stack rm --yes
    $ cd .. && rm -rf pulumi-terraform-test
    
      Guide to Secure Infrastructure Automation