Skip to main content
Pulumi logo Pulumi logo
  1. Docs
  2. Infrastructure as Code
  3. Guides
  4. Basics
  5. Language Essentials
  6. Conditionals

Conditionals

    A conditional decides whether to do something, or which of two things to do, based on a value you already know. You use this constantly in HCL, usually without calling it a conditional: the count = var.enabled ? 1 : 0 idiom is a conditional wearing a resource-repetition costume. A general-purpose language gives you the if statement directly, so you don’t have to route the decision through a resource count.

    Where you have seen this before

    Pulumi YAML has no native conditional, so YAML programs work around the absence with fn::select or by omitting a resource entirely from the file for a given stack. Terraform HCL’s idiom is the conditional count:

    resource "aws_s3_bucket" "backups" {
      count  = var.environment == "production" ? 1 : 0
      bucket = "app-backups"
    }
    

    Everything downstream that used to reference aws_s3_bucket.backups now has to account for it being a list of zero or one items. That’s the tell that HCL is simulating a conditional with a loop, because it doesn’t have a real one.

    The syntax

    A general-purpose language has if/else directly, plus a conditional (ternary) expression for picking between two values. Go doesn’t have a ternary operator, so an if is the idiom there for both cases.

    const instanceSize = environment === "production" ? "m5.large" : "t3.micro";
    
    if (environment === "production") {
      // ...
    }
    
    instance_size = "m5.large" if environment == "production" else "t3.micro"
    
    if environment == "production":
        ...
    
    instanceSize := "t3.micro"
    if environment == "production" {
    	instanceSize = "m5.large"
    }
    
    var instanceSize = environment == "production" ? "m5.large" : "t3.micro";
    
    if (environment == "production")
    {
        // ...
    }
    
    var instanceSize = environment.equals("production") ? "m5.large" : "t3.micro";
    
    if (environment.equals("production")) {
        // ...
    }
    

    Pulumi YAML has no if or ternary expression. fn::select picks a value out of a list by a 0-based integer index, which stands in for a two-way choice when that index itself comes from config:

    config:
      isProduction:
        type: integer
    variables:
      instanceSize:
        fn::select:
          - ${isProduction}
          - - t3.micro
            - m5.large
    

    There’s no way to skip creating a resource entirely from YAML; that requires a general-purpose language or a component.

    HCL has a ternary expression but no if statement, so both branching on a value and deciding whether to create a resource at all go through the conditional expression, the second one via count:

    locals {
      instance_size = var.environment == "production" ? "m5.large" : "t3.micro"
    }
    
    resource "aws_s3_bucket" "backups" {
      count  = var.environment == "production" ? 1 : 0
      bucket = "app-backups"
    }
    

    In a Pulumi program

    Deciding whether to create a resource at all, such as a backup bucket that only exists in production, is a plain if around the resource declaration. pulumi.getStack() returns the current stack name, which is the language equivalent of the stack-scoped variables you’d otherwise branch on in HCL:

    import * as pulumi from "@pulumi/pulumi";
    import * as aws from "@pulumi/aws";
    
    if (pulumi.getStack() === "production") {
      new aws.s3.Bucket("app-backups");
    }
    
    import pulumi
    import pulumi_aws as aws
    
    if pulumi.get_stack() == "production":
        aws.s3.Bucket("app-backups")
    
    package main
    
    import (
    	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/s3"
    	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
    )
    
    func main() {
    	pulumi.Run(func(ctx *pulumi.Context) error {
    		if ctx.Stack() == "production" {
    			if _, err := s3.NewBucket(ctx, "app-backups", nil); err != nil {
    				return err
    			}
    		}
    		return nil
    	})
    }
    
    using Pulumi;
    using Pulumi.Aws.S3;
    
    return await Deployment.RunAsync(() =>
    {
        if (Deployment.Instance.StackName == "production")
        {
            var backups = new Bucket("app-backups");
        }
    });
    
    import com.pulumi.Pulumi;
    import com.pulumi.aws.s3.Bucket;
    
    public class App {
        public static void main(String[] args) {
            Pulumi.run(ctx -> {
                if (ctx.stackName().equals("production")) {
                    var backups = new Bucket("app-backups");
                }
            });
        }
    }
    

    Pulumi YAML has no way to skip declaring a resource based on a condition; every resource in the file is always created. Reaching for a general-purpose language, or a component someone already wrote in one, is the way to make resource creation itself conditional.

    resource "aws_s3_bucket" "backups" {
      count  = terraform.workspace == "production" ? 1 : 0
      bucket = "app-backups"
    }
    

    What to watch out for

    You can’t branch an if statement on a resource output. An output’s value isn’t known while your program is running, so a comparison like if (bucket.arn === "...") doesn’t do what it looks like it does. Branch on values you actually know when the program runs: stack names, configuration, and plain inputs. If a decision genuinely depends on a value that only exists after a resource is created, that decision has to happen inside apply, not in an if statement; see working with outputs for how that works.

    Next steps

    Continue to loops and iteration to see how a for loop replaces count and for_each for creating multiple resources.

      The infrastructure as code platform for any cloud.