Monday, 8 April 2019

Run PowerShell from Terraform

Introduction

As great as Terraform is, you will find times when you need to fall back to running other scripts or using other tools. One such tool is PowerShell. We'll do a quick demo on how to run PowerShell scripts from Terraform configurations.

We've got three options and we'll run through each one:
  1. Run PowerShell from Terraform the first time only
  2. Run PowerShell from Terraform every time
  3. Run PowerShell from Terraform on a trigger
To run PowerShell, we'll be using the null_resource in Terraform. You can find out more about it here. Using the null_resource, we'll be calling the local_exec provisioner which specifies that the PowerShell script will be run on the machine running the Terraform configuration. More info on that is here.

All the code for this blog post can be found on GitHub here.

Run PowerShell from Terraform the first time only

In this example, we want to run a PowerShell script only the first time the Terraform configuration runs.

We have a pretty simple PowerShell script which I'll put in a sub folder called helpers.


Our configuration is pretty simple for this one. Basically, we're calling the null_resource and the local_exec provisioner. We then pass in the path to our PowerShell script and the parameters. Note that you need to dot source your PowerShell script by putting a . before it and you also need to surround it in '' in case the path includes a space. 


We can then run terraform init and terraform apply and we see the output below and we can see Terraform ran the PowerShell script (no, you don't need to run terraform plan).




If we then run terraform apply again, we find that it doesn't run the script:


Run PowerShell from Terraform every time

Note that now we're running the same script every time Terraform runs. Terraform is idempotent which means it only makes changes on the first run and each next run doesn't make a change unless it needs to. Make sure your PowerShell scripts are idempotent if you're using this approach.

The PowerShell script is the same as before and it's in a folder called helpers as before. It's not idempotent but as it's just writing out information to the console it's not causing a problem.

As for the Terraform configuration, we're now adding a trigger which causes Terraform to run each time the trigger value changes. To do this, we're assigning a new UUID each time:


Terraform now runs the PowerShell script every time it runs.


Run PowerShell from Terraform on a defined trigger

Rather than using a UUID as the trigger value, we can configure Terraform to run the PowerShell script only when a particular value changes. In this example, we'll only run the PowerShell script if the value of TriggerValue changes. This can be any output or variable in Terraform e.g. you could specify that only set IP restrictions if the list of IP restrictions changes. 

Again, our PowerShell script is the same as before in the helpers folder.

To demonstrate this, we can add a variable TriggerValue and specify this in a variables.tf file. Terraform will expect us to pass this variable on the command line or via a TFVARS file.


Our Terraform configuration now needs to look like this. See that the trigger option is set to our TriggerValue variable.


When we run our configuration the first time using terraform apply, we need to specify the value for the variable (terraform apply -var TriggerValue=100) and we see that the script runs:



If we run it again, we can see that Terraform has nothing to do and the script doesn't run:


If we change the value of TriggerValue and run it again, Terraform now runs our PowerShell script:




Conclusion

In this article, we went through how you can run PowerShell scripts from Terraform either running every time, on a trigger or on the first time only.