Git-aware directory watching with Terraform
Watching a directory with Terraform in order to update your resources is simple and brilliant! I’ve seen this done many times to do things like update lambda code or S3 bucket websites. The common way to accomplish this is zipping up a source folder with
archive_file and then triggering a
null_resource based on the
output_sha . Here’s an example of that setup:
That’s bad, don’t do that
The problem with
archive_file is that it grabs everything in a directory, including things like
node_modules or build logs. That means
terraform plan will show spurious updates, like when you do a new build or when a team member runs
npm install on their own machine.
You can try to get around this by only zipping up strict source files (e.g.
project/src ); but what about the top-level files like
package.json ? In almost every language, there will be times that you have a combination of important and non-important files in the same directory.
In almost every language, there will be times that you have a combination of important and non-important files in the same directory.
The irony is, you already know which files you do and don’t care about; that’s what a
.gitignore is for!
In this post I’m going to show you an incredibly simple way to only trigger a
null_resource when git-worthy changes are made to your source code.
Hash it up
First, we need a way to create a hash of the directory that only includes files that are important to git. Let’s call them git-portant files. The following bash command does just that:
node_modules , or changing any file ignored in
.gitignore , will not change this hash, but adding new files or changing tracked files will. Awesome!
To track the value of this hash in Terraform so that our
null_resource can depend on it, we’ll use an
external data source. This data source will run the bash script with the specified query and then store the resulting JSON, which will be accessible to the
null_resource . Here’s what that looks like:
Now that’s slick!
The bash script
Now since Terraform interacts with that external source via JSON (in and out), our
gethash.sh is not as simple as the one-liner I showed at the beginning. We’ll need jq to parse the command query, and then we’ll need to output the checksum as JSON for Terraform to read. Here’s the final script:
Simply make sure that:
- The script is executable (
chmod +x gethash.sh)
- It’s in the same directory as your Terraform (or you’ve pointed to it correctly in the tf code)
That’s it! You’re ready to watch that directory for changes with git-telligence!
If this helped you, please like, share, and comment :)