#!/usr/bin/env bash
# Compare every record in a list between two authoritative nameservers.
# usage: dns-diff.sh records.txt OLD_NAMESERVER NEW_NAMESERVER
#   records.txt: one "name type" per line (ns1-to-route53.py writes one)
set -euo pipefail

list=$1 old=$2 new=$3
fail=0
checked=0
while read -r name type || [[ -n "$name" ]]; do
  [[ -z "$name" ]] && continue
  checked=$((checked + 1))
  # +short hides response status: two NXDOMAIN/SERVFAIL/empty replies must not count as a match.
  if ! left=$(dig +norecurse +noall +comments +answer "@$old" "$name" "$type") ||
     ! right=$(dig +norecurse +noall +comments +answer "@$new" "$name" "$type"); then
    echo "ERROR $name $type: query failed"
    fail=1
    continue
  fi
  if [[ "$left" != *"status: NOERROR,"* || "$right" != *"status: NOERROR,"* ]]; then
    echo "ERROR $name $type: a nameserver did not return NOERROR"
    fail=1
    continue
  fi
  # Preserve owner, type and data, but omit TTL and class.
  a=$(awk '!/^;/ && NF >= 5 { printf "%s %s", $1, $4; for (i=5;i<=NF;i++) printf " %s", $i; print "" }' <<< "$left" | sort)
  b=$(awk '!/^;/ && NF >= 5 { printf "%s %s", $1, $4; for (i=5;i<=NF;i++) printf " %s", $i; print "" }' <<< "$right" | sort)
  if [[ -z "$a" || -z "$b" ]]; then
    echo "ERROR $name $type: no answer to verify"
    fail=1
    continue
  fi
  if [[ "$a" != "$b" ]]; then
    echo "DIFF $name $type"
    diff <(echo "$a") <(echo "$b") | sed 's/^/    /' || true
    fail=1
  fi
done < "$list"

if [[ $checked == 0 ]]; then
  echo "ERROR: no records to compare"
  exit 1
fi
[[ $fail == 0 ]] && echo "All records match."
exit $fail
