Learn how to use Terraform's null_resource and local-exec provisions with the AWS CLI to retrieve and utilize data during your infrastructure deployments.
The local-exec provisioner in Terraform allows you to execute scripts or commands on your local machine during Terraform operations. This is particularly helpful for tasks that are not directly supported by Terraform providers, such as interacting with APIs that lack a dedicated provider. Let's explore how it works: First, you define a null_resource. Since local-exec doesn't manage an external resource, null_resource serves as a placeholder. Next, you add the local-exec provisioner within the null_resource block, specifying the command or script to be executed using the command argument. To utilize the output of the command in your Terraform code, you can capture it using the triggers argument within null_resource. However, it's crucial to consider idempotency, ensuring that running the command multiple times produces the same result. Additionally, prioritize security by handling sensitive information cautiously and be mindful that Terraform doesn't track the state of local-exec commands. Let's illustrate this with an example: imagine you need to obtain an API key from a service without a Terraform provider. You can employ local-exec to call a script that retrieves the key, store it in a file, and then utilize the triggers block to read and make the key accessible to other resources.
The local-exec provisioner in Terraform lets you run scripts on your local machine during Terraform operations. It's useful for tasks that the provider doesn't directly support, like interacting with APIs that Terraform doesn't have a provider for.
Here's how it works:
Define a null_resource: The local-exec provisioner is meant to be used within a resource. Since you're not actually managing an external resource, null_resource is a common choice. It acts as a placeholder.
resource "null_resource" "example" {
# ...
}Add the local-exec provisioner: Inside the null_resource block, add a provisioner block with the type local-exec.
resource "null_resource" "example" {
provisioner "local-exec" {
# ...
}
}Specify the command: Within local-exec, use the command argument to define the command you want to execute. This can be a shell command, a script path, or anything your system can run.
resource "null_resource" "example" {
provisioner "local-exec" {
command = "echo 'Hello from local-exec!'"
}
}Capture output (optional): If you need to use the output of the command in your Terraform code, you can capture it using the triggers argument within null_resource.
resource "null_resource" "example" {
provisioner "local-exec" {
command = "echo 'output-value'"
}
triggers = {
output = local.timestamp
}
}
output "captured_output" {
value = null_resource.example.triggers.output
}This example captures the output of the command (output-value) and makes it available as an output variable (captured_output).
Important Considerations:
local-exec should ideally be idempotent, meaning running it multiple times has the same effect as running it once. If your command has side effects, ensure it handles repeated executions gracefully.local-exec commands. Consider using environment variables or other secure mechanisms to pass secrets.local-exec commands. Changes in the command's behavior might not be reflected in Terraform's state.Example: Getting an API Key
Let's say you need to fetch an API key from a service that doesn't have a Terraform provider. You can use local-exec to call a script that retrieves the key:
resource "null_resource" "get_api_key" {
provisioner "local-exec" {
command = "./get_api_key.sh"
}
triggers = {
api_key = filebase64("./api_key.txt")
}
}
resource "some_resource" "example" {
api_key = null_resource.get_api_key.triggers.api_key
}This example assumes you have a script get_api_key.sh that fetches the key and saves it to api_key.txt. The triggers block reads the key from the file and makes it available to other resources.
The code provides examples of using the local-exec provisioner in Terraform. It shows how to print a message, capture command output for tagging resources, and interact with APIs to retrieve and utilize configuration files. The examples highlight using scripts, triggers, and security considerations when working with sensitive information.
This example demonstrates a basic local-exec usage to print a message.
resource "null_resource" "hello_world" {
provisioner "local-exec" {
command = "echo 'Hello from local-exec!'"
}
}This example fetches the current timestamp using a local command and uses it to set a tag on an AWS instance.
resource "null_resource" "get_timestamp" {
provisioner "local-exec" {
command = "date +%Y-%m-%d-%H-%M-%S"
}
triggers = {
timestamp = local.timestamp
}
}
resource "aws_instance" "example" {
# ... other instance configurations ...
tags = {
CreationTime = null_resource.get_timestamp.triggers.timestamp
}
}This example simulates interacting with a hypothetical API to get a configuration file.
resource "null_resource" "get_config" {
provisioner "local-exec" {
command = "./get_config.sh ${var.api_endpoint} ${var.api_token}"
}
triggers = {
config_content = filebase64("./config.json")
}
}
resource "google_storage_bucket_object" "config_object" {
bucket = "my-bucket"
name = "config.json"
source = base64decode(null_resource.get_config.triggers.config_content)
}Explanation:
get_config.sh is a script that interacts with the API using provided endpoint and token.config.json.triggers block reads the content of config.json and makes it available.Important:
get_config.sh, API endpoints, and tokens with your actual values.local-exec. Consider using environment variables or other secure methods.Use Cases:
Best Practices:
Alternatives to Consider:
Debugging:
-verbose flag with Terraform commands to get more detailed logs about local-exec execution.Limitations:
local-exec runs on the machine running Terraform, not on remote resources.local-exec, so be mindful of potential drift between your infrastructure and Terraform's state.| Feature | Description |
|---|---|
| Purpose | Execute scripts or commands on your local machine during Terraform operations. |
| Use Cases | - Interacting with APIs lacking Terraform providers. - Performing tasks outside the scope of Terraform providers. |
| Implementation | 1. Define a null_resource: Acts as a placeholder for the local-exec provisioner. 2. Add the local-exec provisioner: Specify the command to execute using the command argument. 3. Capture output (optional): Use the triggers argument within null_resource to store command output in a variable. |
| Example | Fetching an API key from a service without a Terraform provider using a local script. |
| Considerations | - Idempotency: Ensure commands handle repeated executions gracefully. - Security: Protect sensitive information used in commands. - State: Terraform doesn't track the state of local-exec commands. |
In conclusion, the local-exec provisioner in Terraform is a valuable tool for bridging the gap between Terraform's core functionality and tasks that require local script execution or interaction with unsupported APIs. By using null_resource as a placeholder and carefully considering idempotency and security, you can leverage local-exec to extend Terraform's capabilities and automate a wider range of infrastructure management tasks. However, it's essential to be mindful of its limitations, such as local-only execution and lack of state management, and explore alternative solutions like custom providers or remote execution tools when appropriate. By understanding the strengths and weaknesses of local-exec, you can make informed decisions about when and how to use it effectively in your Terraform configurations.
Getting output from null_resource, local-exec and the AWS CLI. | Hi,. I'm using Terraform to automate provision of Cognito Identity Pools in AWS. The AWS provider doesn't support Cognito yet so I ...
local-exec with providers. If you have worked with terraform for a ... | If you have worked with terraform for a while there is a high chance that you came across local-exec aka a provisioner. Mostly useful when…
Provisioner: local-exec | Terraform | HashiCorp Developer | The local-exec provisioner invokes a local executable after a resource is created. This invokes a process on the machine running Terraform, not on the resource.
How to retrieve the null_resource returned value? - Terraform ... | Hi All, I have the below null_resource to retrieve the prometheus cluster IP: resource "null_resource" "get_prometheus_ip" { provisioner "local-exec" { command = "kubectl get svc prometheus-server -n monitoring | awk -F' ' '{print $3}' | tail -1" } } I want to use its returned result in another place: resource "helm_release" "prometheus-adapter" { name = "prometheus-adapter" chart = "${path.module}/helm/charts/stable/prometheus-adapter/" namespace = "default" // prometheus ...