Terraform OS Detection
In some rare cases it is important to know on which Operating System Terraform is being executed. Since there is (yet) no functionality that solves this, this small hack can help in these situations.
It is important to note that once there hopefully will be an official function by Terraform this hack will become unnecessary.
The situation is the following: We have a functionality in our Terraform code which runs perfectly fine on our build servers which run on Linux.
However, some users run the code on Windows where it fails.
We have found a fix for this, but now we need Terraform to know whether or not it is being run on Linux or Windows.
Let’s get into it.
Create a printf.cmd
file with this content:
@echo off
echo {"os": "Windows"}
We want Terraform to run this file when under Windows which clearly returns to Terraform that we are on Windows. Linux should somehow ignore this file. More on that now:
Create a data.tf
file with this content:
data "external" "os" {
working_dir = path.module
program = ["printf", "{\"os\": \"Linux\"}"]
}
Now comes the magic:
We created a external data resource in Terraform which allows us to run commands outside of Terraform.
working_dir sets the working directory of the program. It is required for this scenario and tells Windows that it should look for a program here in this folder.
program This is the essential hack: Under Windows the OS will look for an executable called printf in the working directory, which it finds as printf.cmd. Remember Windows ignores file extensions! It will pass the second argument ({\"os\": \"Linux\"}
) of program = ["printf", "{\"os\": \"Linux\"}"]
to the executable printf.cmd, which simply ignores them because it does not expect any. Instead, printf.cmd will simply return "{os": "Windows}"
as we defined in the first code snippet.
Now here is the catch: Linux will before looking for a program printf in the working directory look for a program called printf under its binaries. Et voilà Linux has its binary printf which simply prints what you give it as an argument (printf). As we have defined here (program = ["printf", "{\"os\": \"Linux\"}"]
) we give to printf the argument {\"os\": \"Linux\"}
and therefore it will print exactly that: That we are under Linux, ignoring the printf.cmd file in the working directory.
Now all that is left is to access the results:
Create a locals.tf
file with this content:
locals {
os = data.external.os.result.os
check = local.os == "Windows" ? "We are on Windows" : "We are on Linux"
}
As you can see with defining the local variable os
we execute our data resource data "external" "os"
from before and by using result
we can get its result. os
by now should be either Windows
or Linux
. With check
we can then check if the underlying OS is either Windows or Linux.
In the scenario it is now possible to detect on which OS Terraform is being run and we can implement the fix.
Credits:
Janos Pasztor for the idea and concept.
To my colleague Philipp , who impresses me with his sharpness every other day and with whom I came up with this solution.
tl;dr:
printf.cmd
:
@echo off
echo {"os": "Windows"}
data.tf
:
data "external" "os" {
working_dir = path.module
program = ["printf", "{\"os\": \"Linux\"}"]
}
locals.tf
:
locals {
os = data.external.os.result.os
check = local.os == "Windows" ? "We are on Windows" : "We are on Linux"
}