Using Git Hooks with Datree

Using Git Hooks with Datree

Datree is an excellent command-line tool that helps identify misconfiguration in Kubernetes files and integrates perfectly with most CI/CD tools.

Datree creates automated policy checks and prevents misconfiguration in your Kubernetes file from reaching production by identifying issues early and explaining how to fix them.

Git is a distributed version control system that tracks changes to a file so that you can recall specific versions later.

Git Hooks

Git hooks are scripts that run automatically every time a particular event occurs in a Git repository (e.g. $ git commit, $ git push, etc.)

Scripts are bash commands bundled in a text file to run as a program.

These hooks are located in the .git/hooks dir after initializing a git repo locally i.e git init

$ ls -1 .git/hooks/
applypatch-msg.sample
commit-msg.sample
fsmonitor-watchman.sample
post-update.sample
pre-applypatch.sample
pre-commit.sample
pre-merge-commit.sample
prepare-commit-msg.sample
pre-push.sample
pre-rebase.sample
pre-receive.sample
update.sample

Git pre-commit example

In this example, every time git commit is used, a bash script will run. In that script, there will be a check for any Kubernetes files.

If any, Datree will be run on it to check for misconfiguration. If the Kubernetes file passes the test then the git commit will be successful else, the git commit won't be successful.

These are the steps:

  1. Create a new directory, change the present working directory into your newly created directory, and initialize git

     mkdir example
     cd example
     git init
     cd .git/hooks
     ls .
    
  2. Rename pre-commit.sample

    Remove the .sample from the pre-commit.sample hook.

     mv pre-commit.sample pre-commit
    
  3. Add script to the pre-commit hook

    Open the pre-commit file using your favorite code editor and add the below commands.

     #!usr/bin/env bash
    
     # Grep all yaml files that are part of the commit
     YAML_STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep ".ya\?ml\$")
    
     if [ "$YAML_STAGED_FILES" = "" ]; then
       exit 0
     fi
    
     # K8s yaml validation
     YAML_PASS=true
     if [ ! "$YAML_STAGED_FILES" = "" ]; then
       echo -e "$(tput setaf 7)$(tput bold)INFO: $(tput init)Validating K8s files with Datree..."
    
       for YAML_FILE in $YAML_STAGED_FILES
       do
         # Skip yaml files that are not k8s files
         apiVersionResult="$(yq e '.apiVersion' "$YAML_FILE")"
         kindResult="$(yq e '.kind' "$YAML_FILE")"
    
         if [ "$apiVersionResult" = "null" ] && [ "$kindResult" = "null" ]; then
           echo -e "$(tput setaf 3)$(tput bold)WARNING: $(tput init)Could not find a 'kind' or 'apiVersion' attribute in $YAML_FILE, skipping..."
           continue
         fi
    
         # Run datree on all the other yaml files
         if datree test "$YAML_FILE"; then
           echo -e "$(tput setaf 2)$(tput bold)Datree Passed: $(tput init)$YAML_FILE"
         else
           echo -e "$(tput setaf 1)$(tput bold)Datree Failed: $(tput init)$YAML_FILE"
           YAML_PASS=false
         fi
       done
     fi
    
     # Exit and give status
     if [ "$YAML_PASS" = "false" ]; then
       echo -e "$(tput setaf 1)$(tput bold)ERROR: $(tput init)Your commit contains files that failed Datree tests. Please fix the errors and try again."
       exit 1
     fi
    
     echo -e "\n$(tput setaf 2)$(tput bold)COMMIT SUCCEEDED$(tput init)"
     exit $?
    

That's it!

With this script, every time you make a commit, the bash script will look for all the Kubernetes yaml files that have been committed and will run datree test [yaml file] on each of them.