slide

Terraform fot d signum()

Ned Bellavance
3 min read

Cover

This is part of an ongoing series of posts documenting the built-in interpolation functions in Terraform. For more information, check out the beginning post. In this post I am going to cover the signum() function. The example file is on GitHub here.

What is it?

Function name: signum(int)

Returns: Takes an int and returns -1 if negative, 0 if 0, and 1 if positive

Example:

# Returns 0
output "signum_output" {
  value = "${signum("0")}"
}

Example file:

##############################################
# Function: signum
##############################################
##############################################
# Variables
##############################################
variable "signum" {
  default = 0
}

##############################################
# Resources
##############################################

##############################################
# Outputs
##############################################
output "signum_output" {
  value = "${signum(var.signum)}"
}

Run the following from the signum folder to get example output for a number of different cases:

#base case returns 0
terraform apply

#negative 0 is fine
terraform apply -var "signum=-0"

#returns 1
terraform apply -var "signum=1"

#returns  -1
terraform apply -var "signum=-1"

#returns 1
terraform apply -var "signum=42"

#returns -1
terraform apply -var "signum=-42"

#errors, the max positive value is 1e+18
terraform apply -var "signum=10000000000000000000"

#errors, the max negative value is -1e+18
terraform apply -var "signum=-10000000000000000000"

Why use it?

This function is dead simple. And I really don’t know why you would use it. It provides a way to determine if an int is negative, positive, or 0. The suggested use case in the official doc is to have one value for the first item in a list, and another value for the rest. If that’s not clear, let’s say you have a list of resources [main, other1, other2, other3] and another list of settings [main_settings, other_settings]. Then you could use signum to assign the proper settings to each resource in the list based on a count loop.

element(list(main_settings,other_settings),signum(count.index))

For the first iteration of the loop your count is 0, and the element function returns main_settings. The rest of the loop counts resolve to 1, and the element function returns other_settings. I thought for sure that this function was built into Golang’s math package, but no! Someone actually took the time to write a function to natively handle the operation. Here’s the code in case you were curious.


func interpolationFuncSignum() ast.Function {
    return ast.Function{
        ArgTypes:   []ast.Type{ast.TypeInt},
        ReturnType: ast.TypeInt,
        Variadic:   false,
        Callback: func(args []interface{}) (interface{}, error) {
            num := args[0].(int)
            switch {
            case num < 0:
                return -1, nil
            case num > 0:
                return +1, nil
            default:
                return 0, nil
            }
        },
    }
}

So I guess someone felt strongly enough that this should be part of the native functions in Terraform. And to them I say, “You go, Glen Coco!”

Mean Girls is the best.

Lessons Learned

Well, I learned that the max value for the int type is 1 quintillion. That’s probably big enough. I also learned that -0 evaluates without an issue. That’s pretty much it. To be honest, I think I said it all in the Why use it section.

Coming up next is the slice() function. Sadly, there is no sprite function.