Learn how Terraform detects changes and if it can automatically monitor a directory for modifications to your infrastructure code.
Terraform, a powerful infrastructure-as-code tool, doesn't natively support automatic directory watching and triggering actions like "terraform apply" upon changes. However, this can be achieved using external scripting and tools. A common approach involves using a scripting language like Python to monitor a directory for modifications and execute Terraform commands when changes are detected.
Terraform itself doesn't have a built-in feature to automatically watch a directory for changes and trigger actions like "terraform apply". However, you can achieve this behavior using external scripting and tools. Here's a common approach using a scripting language like Python:
Calculate Directory Checksum:
Watch for Changes:
watchdog in Python to monitor the directory for any changes (file modifications, additions, deletions).Compare Checksums:
watchdog library detects a change:
Trigger Terraform Actions:
terraform plan and terraform apply using Python's subprocess module or similar.Example (Conceptual Python Code):
import time
import hashlib
import subprocess
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class Watcher:
def __init__(self, directory_to_watch):
self.directory_to_watch = directory_to_watch
self.initial_checksum = self.calculate_checksum()
def calculate_checksum(self):
# Logic to calculate directory checksum (e.g., using hashlib.md5())
def run(self):
event_handler = Handler()
observer = Observer()
observer.schedule(event_handler, self.directory_to_watch, recursive=True)
observer.start()
try:
while True:
time.sleep(5)
except:
observer.stop()
observer.join()
class Handler(FileSystemEventHandler):
@staticmethod
def on_any_event(event):
if not event.is_directory:
# Directory modified, recalculate checksum and compare
new_checksum = Watcher.calculate_checksum()
if new_checksum != Watcher.initial_checksum:
# Trigger Terraform actions
subprocess.run(["terraform", "plan"])
subprocess.run(["terraform", "apply", "-auto-approve"]) # Be cautious with auto-approve
if __name__ == "__main__":
w = Watcher("/path/to/your/terraform/directory")
w.run()Important Considerations:
entr or fswatch for directory watching, and integrate them with Terraform execution.Remember to adapt this approach to your specific use case and environment.
This Python script uses the 'watchdog' library to monitor a specified directory for changes. When a change is detected, it calculates the directory's checksum and compares it to the initial checksum. If the checksums differ, indicating modifications, the script executes 'terraform plan' and 'terraform apply' commands within the specified directory to automatically update the infrastructure based on the changes made to the Terraform files. The script is designed to continuously monitor the directory and automatically apply Terraform changes, simplifying the process of keeping infrastructure configurations up-to-date.
import time
import hashlib
import subprocess
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class Watcher:
def __init__(self, directory_to_watch):
self.directory_to_watch = directory_to_watch
self.initial_checksum = self.calculate_checksum()
def calculate_checksum(self):
# Logic to calculate directory checksum using hashlib.md5()
hash_md5 = hashlib.md5()
for root, _, files in os.walk(self.directory_to_watch):
for file in files:
filepath = os.path.join(root, file)
with open(filepath, "rb") as f:
for chunk in iter(lambda: f.read(4096), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest()
def run(self):
event_handler = Handler(self)
observer = Observer()
observer.schedule(event_handler, self.directory_to_watch, recursive=True)
observer.start()
try:
print(f"Watching directory: {self.directory_to_watch}")
while True:
time.sleep(5)
except KeyboardInterrupt:
observer.stop()
observer.join()
class Handler(FileSystemEventHandler):
def __init__(self, watcher):
self.watcher = watcher
def on_any_event(self, event):
if not event.is_directory:
new_checksum = self.watcher.calculate_checksum()
if new_checksum != self.watcher.initial_checksum:
print("Changes detected. Running Terraform...")
try:
subprocess.run(["terraform", "plan"], cwd=self.watcher.directory_to_watch, check=True)
subprocess.run(["terraform", "apply", "-auto-approve"], cwd=self.watcher.directory_to_watch, check=True)
print("Terraform apply successful!")
self.watcher.initial_checksum = new_checksum # Update checksum after successful apply
except subprocess.CalledProcessError as e:
print(f"Error executing Terraform: {e}")
if __name__ == "__main__":
import os
terraform_dir = os.path.join(os.getcwd(), "path/to/your/terraform/directory") # Replace with your Terraform directory
w = Watcher(terraform_dir)
w.run()Explanation:
Import Necessary Modules:
time: For pausing execution.hashlib: For calculating MD5 checksums.subprocess: For running Terraform commands.watchdog: For monitoring directory changes.Watcher Class:
__init__: Initializes the watcher with the target directory and calculates the initial checksum.calculate_checksum: Calculates the MD5 checksum of the directory.run:
Handler object to handle file system events.Observer object and schedules the handler to watch the directory recursively.Handler Class (Inherits from FileSystemEventHandler):
on_any_event: This method is triggered on any file system event (modification, creation, deletion).
subprocess.run to execute terraform plan and terraform apply (with -auto-approve - use caution!).cwd argument in subprocess.run is crucial to set the working directory for Terraform commands to the correct path.initial_checksum after a successful terraform apply to avoid redundant executions.Main Execution Block (if __name__ == "__main__":)
terraform_dir variable to the path of your Terraform project directory.Watcher instance, passing in the terraform_dir.run() method of the watcher to start the monitoring process.How to Use:
Install watchdog:
pip install watchdogSave the Code: Save the code as a Python file (e.g., terraform_watcher.py).
Modify terraform_dir: Replace "path/to/your/terraform/directory" with the actual path to your Terraform project directory.
Run the Script:
python terraform_watcher.pyNow, the script will continuously monitor your Terraform directory and automatically apply changes whenever it detects modifications to the files within.
Functionality:
calculate_checksum function demonstrates a robust way to calculate a directory's checksum using hashlib.md5(). It iterates through all files within the directory and its subdirectories, ensuring any change is detected.cwd argument in subprocess.run is essential for setting the correct working directory when executing Terraform commands. This ensures Terraform operates on the intended directory structure.try-except block to catch subprocess.CalledProcessError. This helps identify issues during Terraform command execution.Improvements:
Alternatives:
Security:
-auto-approve in the script should be carefully considered. While convenient, it bypasses any manual review or approval steps, potentially leading to unintended consequences.While Terraform lacks built-in directory watching, you can achieve this using external scripts and tools. Here's a common approach:
1. Directory Checksumming:
2. Change Detection:
watchdog to monitor the directory for any file changes (modifications, additions, deletions).3. Checksum Comparison:
4. Triggering Terraform:
terraform plan, terraform apply) using Python's subprocess module or similar.Key Considerations:
entr or fswatch for directory watching and integrate them with Terraform execution.This approach provides a basic framework. Adapt and customize it based on your specific needs and environment.
This approach, while effective, necessitates careful consideration of error handling, idempotency of Terraform code, and security implications, especially when using "auto-approve." Alternative tools like entr or fswatch can be explored for directory watching. Remember to tailor this approach to your specific use case and environment for optimal results. By implementing such a solution, you can leverage the power of automation to streamline your infrastructure management workflow, ensuring that your infrastructure remains consistent with your Terraform codebase.
Changing workspace directory - state file - HCP Terraform ... | We currently use different workspaces for our DEV and PROD accounts, but the structure is not currently split by environment. I want to move over to a more modular approach as well as having the environments in their own directories. My question is, if I do this refactoring and change the directory under which the workspace runs, do I need to do anything to also move the location of the state file (as the docs say it is stored in the root of the directory it runs under, and this will now be a s...
Confusing error message when terraform backend is changed ... | I am using s3 as terraform backend to manage AWS resources, and recently I enabled SSO for AWS by adding a SSO profile in the s3 provider as below. backend "s3" { bucket = "test-bucket-xxx" key = "terraform" region = "us-west-2" profile = "xxx" } Error: Backend configuration changed A change in the backend configuration has been detected, which may require migrating existing state. If you wish to attempt automatic migration of the state, use “terraform init -migrat...
CLI Commands - CDK for Terraform | Terraform | HashiCorp ... | synth -- Synthesizes Terraform code for the given app in a directory. watch -- [experimental] Watch for file changes and automatically trigger a deploy ...
How to run terraform plan locally when using Terraform cloud - HCP ... | Previously I could change the terraform script, run the terraform plan command and see the changes that would be applied locally. I do this, before committing the changes into git and pushing to the central repository. Now at work we have moved to Terraform Cloud and it seems the workflow I used is no longer possible. Now with Terraform Cloud, I need to first commit and push the changes first before being apply to see the results of a command like terraform plan I believe this reduces the feed...
Configuring Github Actions in a multi-directory repository structure ... | Hello World!dev_overrides · Issue #24 ... | This was initially left out from implementation of #16 due to scope/complexity. https://www.terraform.io/docs/configuration/providers.html#provider-plugin-cache LS currently won't be able to load s...