terom@525: #!/bin/bash terom@525: # vim: set ft=sh : terom@525: terom@525: set -ue terom@525: terom@567: terom@567: ### Paths terom@525: ROOT=$(pwd) terom@525: terom@551: # resolve $0 terom@551: self=$0 terom@551: while [ -L $self ]; do terom@554: tgt=$(readlink $self) terom@554: terom@554: if [ "${tgt:0:1}" == "/" ]; then terom@554: self=$tgt terom@554: else terom@554: self=$(dirname $self)/$tgt terom@554: fi terom@551: done terom@551: terom@567: # Our bin dir, with scripts terom@551: BIN=$(dirname $self) terom@525: terom@567: # Data files terom@544: DATA=settings terom@530: ZONES=zones terom@544: SERIALS=$DATA terom@570: REPO=. terom@525: terom@567: # Script/data args terom@525: PROCESS_ARGS='--input-charset latin-1' terom@525: terom@551: # external progs terom@533: NAMED_CHECKZONE=/usr/sbin/named-checkzone terom@554: HG=/usr/bin/hg terom@550: RNDC=/usr/sbin/rndc terom@569: RNDC_KEY=/etc/bind/rndc.key terom@533: terom@567: ### Command-line argument handling terom@567: terom@530: IS_TTY= terom@531: terom@567: ## Options terom@567: LOG_ERROR=y terom@554: LOG_WARN=y terom@531: LOG=y terom@566: LOG_FORCE=y terom@566: LOG_UPDATE=y terom@566: LOG_NOOP=y terom@564: LOG_SKIP= terom@531: LOG_DEBUG= terom@531: LOG_CMD= terom@531: terom@530: UPDATE_FORCE= terom@531: UPDATE_NOOP= terom@531: UPDATE_DIFF= terom@566: terom@566: SERIAL_NOOP= terom@566: SERIAL_FORCE= terom@566: terom@544: COMMIT_SKIP= terom@544: COMMIT_FORCE= terom@545: COMMIT_MSG=' ' terom@530: terom@550: DEPLOY_SKIP= terom@550: terom@567: ## Output command-line argument help. terom@530: function help_args { terom@530: local prog=$1 terom@530: terom@530: cat <&2 terom@525: } terom@525: terom@567: # Output message to stderr, optionally with given color, if TTY. terom@530: function log_color { terom@530: local code=$1; shift terom@530: terom@530: if [ $IS_TTY ]; then terom@564: echo $'\e['${code}'m'"$*"$'\e[00m' >&2 terom@530: else terom@530: echo "$*" >&2 terom@530: fi terom@530: } terom@530: terom@567: ## Log at various log-levels terom@567: terom@530: function log_error { terom@567: [ $LOG_ERROR ] && log_color '31' "$*" terom@530: } terom@530: terom@554: function log_warn { terom@564: [ $LOG_WARN ] && log_color '33' "$*" || true terom@554: } terom@554: terom@567: # plain terom@530: function log { terom@531: [ $LOG ] && log_msg "$*" || true terom@530: } terom@530: terom@566: function log_force { terom@566: [ $LOG_FORCE ] && log_color '2;33' " $*" || true terom@566: } terom@566: terom@566: function log_update { terom@566: [ $LOG_UPDATE ] && log_color '36' " $*" || true terom@566: } terom@566: terom@566: function log_noop { terom@566: [ $LOG_NOOP ] && log_color '2;34' " $*" || true terom@564: } terom@564: terom@564: function log_skip { terom@564: [ $LOG_SKIP ] && log_color '1;34' " $*" || true terom@530: } terom@530: terom@530: function log_debug { terom@531: [ $LOG_DEBUG ] && log_color 32 " $*" || true terom@530: } terom@530: terom@530: function log_cmd { terom@531: [ $LOG_CMD ] && log_color 35 " \$ $*" || true terom@531: } terom@531: terom@567: # Output stacktrace, broken. terom@531: function log_stack { terom@531: local level=1 terom@531: terom@531: while info=$(caller $level); do terom@531: echo $info | read line sub file terom@531: terom@531: log_msg "$file:$lineno $sub()" terom@531: terom@531: level=$(($level + 1)) terom@531: done terom@531: } terom@531: terom@567: # Output calling function's name. terom@565: function func_caller { terom@565: caller 1 | cut -d ' ' -f 2 terom@565: } terom@565: terom@567: ### High-level logging output terom@567: # Log with func_caller at log_debug terom@565: function debug { terom@565: printf -v prefix "%s" $(func_caller) terom@565: terom@565: log_debug "$prefix: $*" terom@565: } terom@565: terom@567: # Log with func_caller at log_error and exit, intended for internal errors... terom@531: function fail { terom@565: log_error "$(func_caller): $*" terom@531: terom@531: exit 2 terom@530: } terom@530: terom@567: # Log at log_error and exit terom@525: function die { terom@530: log_error "$*" terom@525: exit 1 terom@525: } terom@525: terom@567: ### Command execution terom@567: ## Execute command, possibly logging its execution. terom@567: # terom@567: # cmd $cmd... terom@567: # terom@567: # Fails if the command returns an error exit code. terom@530: function cmd { terom@530: log_cmd "$@" terom@530: terom@530: "$@" || die "Failed" terom@530: } terom@530: terom@530: function indent () { terom@531: local indent=$1; shift terom@531: terom@541: log_cmd "$@" terom@541: terom@549: "$@" | sed "s/^/$indent/" terom@554: terom@554: return ${PIPESTATUS[0]} terom@541: } terom@541: terom@567: terom@567: ### FS utils terom@567: # Create dir in $ROOT if not exists. terom@564: function ensure_dir { terom@564: local dir=$1 terom@564: terom@564: if [ ! -d $ROOT/$dir ]; then terom@564: log_warn "Creating output dir: $dir" terom@564: cmd mkdir $ROOT/$dir terom@564: fi terom@564: } terom@564: terom@567: ## Output absolute path from $ROOT: terom@567: # terom@567: # abspath $path terom@567: # terom@541: function abspath () { terom@567: local path=$1 terom@567: terom@567: echo "$ROOT/$path" terom@530: } terom@530: terom@567: ### HG wrappers terom@567: # Run `hg ...` within $REPO. terom@551: function hg { terom@570: local repo=$REPO terom@551: terom@554: cmd $HG -R $ROOT/$repo "$@" terom@551: } terom@551: terom@567: # Does the repo have local modifications? terom@551: function hg_modified { terom@562: hg id | grep -q '+' terom@551: } terom@551: terom@567: # Output possible -u flag for commit. terom@551: function hg_user { terom@551: if [ ${SUDO_USER:-} ]; then terom@551: echo '-u' "$SUDO_USER" terom@551: terom@551: elif [ $HOME ] && [ -e $HOME/.hgrc ]; then terom@565: debug "using .hgrc user" terom@551: echo '' terom@551: terom@551: else terom@551: echo '-u' "$USER" terom@551: fi terom@551: } terom@551: terom@567: # Show changes in repo terom@551: function hg_diff { terom@562: hg diff terom@551: } terom@551: terom@567: ## Commit changes in repo, with given message: terom@567: # terom@567: # hg_commit $msg terom@567: # terom@551: function hg_commit { terom@567: local msg=$1 terom@551: local user_opt=$(hg_user) terom@551: terom@565: debug "$user_opt: $msg" terom@562: hg commit $user_opt -m "$msg" terom@551: } terom@551: terom@525: terom@567: ### Dependency-based updates terom@566: terom@567: ## Compare the given output file with all given source files: terom@567: # terom@567: # check_update $out ${deps[@]} && do_update $out ... || ... terom@566: # terom@566: # Returns true if the output file needs to be updated. terom@531: function check_update { terom@531: # target terom@567: local out=$1; shift terom@531: terom@567: debug "$out" terom@531: terom@531: # need update? terom@531: local update= terom@531: terom@565: if [ ${#@} == 0 ]; then terom@565: debug " update: unknown deps" terom@565: update=y terom@565: terom@567: elif [ ! -e $out ]; then terom@565: debug " update: dest missing" terom@565: update=y terom@565: terom@565: elif [ $UPDATE_FORCE ]; then terom@565: debug " update: forced" terom@531: update=y terom@531: fi terom@531: terom@531: # check deps terom@531: for dep in "$@"; do terom@531: # don't bother checking if already figured out terom@531: [ $update ] && continue terom@531: terom@531: # check terom@564: if [ ! -e $ROOT/$dep ]; then terom@564: fail "$dst: Missing source: $dep" terom@531: terom@567: elif [ $ROOT/$out -ot $ROOT/$dep ]; then terom@565: debug " update: $dep" terom@531: update=y terom@565: else terom@565: debug " check: $dep" terom@531: fi terom@531: done terom@531: terom@565: [ ! $update ] && debug " up-to-date" terom@531: terom@531: # return terom@531: [ $update ] terom@531: } terom@531: terom@567: ## Generate updated output file from given command's stdout: terom@567: # terom@567: # do_update $out $BIN/cmd --args terom@567: # terom@567: # Writes output to a temporary .new file, optionally shows a diff of changes, and commits terom@567: # the new version to $out (unless noop'd). terom@531: function do_update { terom@567: local out=$1; shift terom@567: local tmp=$out.new terom@530: terom@567: debug "$out" terom@551: cmd "$@" > $ROOT/$tmp terom@530: terom@531: # compare terom@567: if [ -e $ROOT/$out ] && [ $UPDATE_DIFF ]; then terom@565: debug " changes:" terom@531: terom@531: # terse terom@567: indent " " diff --unified=1 $ROOT/$out $ROOT/$tmp || true terom@531: fi terom@531: terom@567: # deploy terom@531: if [ $UPDATE_NOOP ]; then terom@531: # cleanup terom@565: debug " no-op" terom@531: terom@551: cmd rm $ROOT/$tmp terom@531: else terom@531: # commit terom@567: debug " deploy" terom@531: terom@567: cmd mv $ROOT/$tmp $ROOT/$out terom@531: fi terom@531: } terom@531: terom@567: ## Look for a link target: terom@567: # terom@567: # find_link $lnk $tgt... terom@567: # terom@567: # Outputs the first given target to exist, skipping any that are the same as the given $lnk. terom@567: # If no $tgt matches, outputs the last one, or '-'. terom@567: function choose_link { terom@567: local lnk=$1; shift terom@567: local tgt=- terom@567: terom@567: for tgt in "$@"; do terom@567: [ $tgt != $out ] && [ -e $ROOT/$tgt ] && break terom@567: done terom@567: terom@567: echo $tgt terom@567: } terom@567: terom@567: terom@567: ## Compare symlink to target: terom@567: # terom@567: # check_link $lnk $tgt && do_link $lnk $tgt || ... terom@567: # terom@567: # Tests if the symlink exists, and the target matches. terom@567: # Fails if the target does not exist. terom@561: function check_link { terom@561: local lnk=$1 terom@561: local tgt=$2 terom@567: terom@567: [ ! -e $ROOT/$tgt ] && fail "$tgt: target does not exist" terom@537: terom@561: [ ! -e $ROOT/$lnk ] || [ $(readlink $ROOT/$lnk) != $ROOT/$tgt ] terom@561: } terom@531: terom@567: ## Update symlink to point to target: terom@567: # terom@567: # do_link $lnk $tgt terom@567: # terom@561: function do_link { terom@561: local lnk=$1 terom@561: local tgt=$2 terom@531: terom@561: cmd ln -sf $ROOT/$tgt $ROOT/$lnk terom@561: } terom@561: terom@567: ## Update .serial number: terom@567: # terom@567: # do_update_serial $serial terom@567: # terom@567: # Shows old/new serial on debug. terom@565: function do_update_serial { terom@565: local serial=$1 terom@565: terom@564: # read terom@561: local old=$(test -e $ROOT/$serial && cat $ROOT/$serial || echo '') terom@561: terom@561: terom@564: cmd $BIN/update-serial $ROOT/$serial terom@561: terom@564: # read terom@561: local new=$(cat $ROOT/$serial) terom@531: terom@565: debug " $old -> $new" terom@565: } terom@565: terom@567: ## Perform `hg commit` for $DATA terom@567: function do_commit { terom@567: local msg=$1 terom@567: terom@567: indent " " hg_diff terom@567: terom@567: hg_commit "$msg" terom@567: } terom@567: terom@567: ### Hosts terom@567: ## Update hosts from verbatim from input zone data: terom@567: # terom@567: # copy_hosts $ZONES/$zone $DATA/$base terom@567: # terom@567: # Writes updated zone to $zone, deps on $base. terom@567: function copy_hosts { terom@567: local zone=$1 terom@567: local base=$2 terom@567: terom@567: if check_update $zone $base; then terom@567: log_update "Copying hosts $zone <- $base..." terom@567: terom@567: do_update $zone \ terom@567: cat $ROOT/$base terom@567: else terom@567: log_skip "Copying hosts $zone <- $base: not changed" terom@567: fi terom@567: } terom@567: terom@567: ## Generate hosts from input zone data using $BIN/process-zone: terom@567: # terom@567: # update_hosts $ZONES/$zone $DATA/$base terom@567: # terom@567: # Writes process-zone'd data to $zone, deps on $base. terom@567: function update_hosts { terom@567: local zone=$1; shift terom@567: local base=$1; shift terom@567: terom@567: if check_update $zone $base; then terom@567: log_update "Generating hosts $zone <- $base..." terom@567: terom@567: do_update $zone \ terom@567: $BIN/process-zone $PROCESS_ARGS $ROOT/$base "$@" terom@567: else terom@567: log_skip "Generating hosts $zone <- $base: not changed" terom@567: fi terom@567: } terom@567: terom@567: ## Generate new serial for zone using $BIN/update-serial, if the zone data has changed: terom@567: # terom@567: # update_serial $zone $deps... terom@567: # terom@567: # Supports SERIAL_FORCE/NOOP. terom@567: # Updates $SERIALS/$zone.serial. terom@565: function update_serial { terom@565: local zone=$1; shift terom@565: terom@565: local serial=$SERIALS/$zone.serial terom@565: terom@565: # test terom@566: if [ $SERIAL_FORCE ]; then terom@566: log_force "Updating $serial: forced" terom@566: terom@566: do_update_serial $serial terom@566: terom@566: elif ! check_update $serial "$@"; then terom@565: log_skip "Updating $serial: not changed" terom@565: terom@566: elif [ $SERIAL_NOOP ]; then terom@566: log_noop "Updating $serial: skipped" terom@565: terom@565: else terom@566: log_update "Updating $serial..." terom@565: terom@565: do_update_serial $serial terom@565: fi terom@530: } terom@530: terom@567: ## Link serial for zone from given base-zone: terom@567: # terom@567: # link_serial $zone $base terom@561: function link_serial { terom@561: local zone=$1 terom@559: local base=$2 terom@559: terom@561: local lnk=$SERIALS/$zone.serial terom@559: local tgt=$SERIALS/$base.serial terom@559: terom@561: if check_link $lnk $tgt; then terom@566: log_update "Linking $lnk -> $tgt..." terom@561: terom@561: do_link $lnk $tgt terom@559: terom@559: else terom@564: log_skip "Linking $lnk -> $tgt: not changed" terom@559: fi terom@559: } terom@559: terom@567: ## Update zone file verbatim from source: terom@567: # terom@567: # copy_zone $view $zone [$base] terom@567: # terom@567: # Copies changed $DATA/$base zone data to $ZONES/$view/$zone. terom@561: function copy_zone { terom@561: local view=$1 terom@561: local zone=$2 terom@561: local base=${3:-$zone} terom@525: terom@561: local out=$ZONES/$view/$zone terom@561: local src=$DATA/$base terom@530: terom@561: if check_update $out $src; then terom@566: log_update "Copying $out <- $src..." terom@531: terom@564: do_update $out \ terom@564: cat $ROOT/$src terom@531: else terom@564: log_skip "Copying $out <- $src: not changed" terom@531: fi terom@525: } terom@525: terom@567: ## Expand zone file from source using $BIN/expand-zone: terom@567: # terom@567: # update_zone $view $zone [$base] terom@567: # terom@567: # Processed $DATA/$base zone data through $BIN/expand-zone, writing output to $ZONES/$view/$zone. terom@525: function update_zone { terom@561: local view=$1 terom@561: local zone=$2 terom@561: local base=${3:-$zone} terom@531: terom@561: local out=$ZONES/$view/$zone terom@561: local src=$DATA/$base.zone terom@561: local lnk=$ZONES/$base terom@564: terom@561: local serial=$SERIALS/$base.serial terom@530: terom@564: if check_update $out $src $serial; then terom@566: log_update "Generating $out <- $src..." terom@531: terom@531: do_update $out \ terom@563: $BIN/expand-zone $ROOT/$src \ terom@561: --serial $ROOT/$serial \ terom@541: --expand zones=$(abspath $ZONES) \ terom@531: --expand view=$view terom@531: else terom@564: log_skip "Generating $out <- $src: not changed" terom@531: fi terom@531: } terom@531: terom@567: ## Link zone file to ues given shared zone. terom@567: # terom@567: # link_zone $view $zone [$base] terom@567: # terom@567: # Looks for shared zone at: terom@567: # $ZONES/$view/$base terom@567: # $ZONES/common/$base terom@561: function link_zone { terom@561: local view=$1 terom@561: local zone=$2 terom@561: local base=${3:-$zone} terom@559: terom@561: local out=$ZONES/$view/$zone terom@567: local tgt=$(choose_link $out $ZONES/$view/$base $ZONES/common/$base) terom@559: terom@561: if check_link $out $tgt; then terom@566: log_update "Linking $out -> $tgt..." terom@561: terom@561: do_link $out $tgt terom@567: terom@553: else terom@564: log_skip "Linking $out -> $tgt: not changed" terom@553: fi terom@553: } terom@553: terom@567: ## Test hosts zone for validity: terom@567: # terom@567: # check_hosts $DATA/$hosts --check-exempt ... terom@567: # terom@567: # Fails if the check fails. terom@536: function check_hosts { terom@536: local hosts=$1; shift 1 terom@536: terom@563: local cmd=($BIN/process-zone $PROCESS_ARGS $ROOT/$hosts --check-hosts "$@") terom@536: terom@536: if "${cmd[@]}" -q; then terom@564: log_skip "Check $hosts: OK" terom@536: else terom@536: log_error " Check $hosts: Failed" terom@536: terom@536: indent " " "${cmd[@]}" terom@536: terom@536: exit 1 terom@536: fi terom@536: } terom@536: terom@567: ## Test zone file for validity using named-checkzone: terom@567: # terom@567: # check_zone $view $zone $origin terom@567: # terom@567: # Uses the zonefile at $ZONES/$view/$zone, loading it with given initial $ORIGIN. terom@567: # Fails if the check fails. terom@533: function check_zone { terom@561: local view=$1 terom@561: local zone=$2 terom@561: local origin=$3 terom@533: terom@561: local src=$ZONES/$view/$zone terom@561: terom@561: local cmd=($NAMED_CHECKZONE $origin $ROOT/$src) terom@536: terom@533: # test terom@536: # XXX: checkzone is very specific about the order of arguments, -q must be first terom@561: if $NAMED_CHECKZONE -q $origin $ROOT/$src; then terom@564: log_skip "Check $src ($origin): OK" terom@533: else terom@561: log_error " Check $src ($origin): Failed:" terom@533: terom@536: indent " " "${cmd[@]}" terom@536: terom@536: exit 1 terom@533: fi terom@533: } terom@533: terom@567: ## Load update zonefiles into bind: terom@567: # terom@567: # deploy_zones terom@567: # terom@567: # Invokes `rndc reload`, showing its output. terom@550: function deploy_zones { terom@569: local msg="Reload zones" terom@569: terom@567: if [ $DEPLOY_SKIP ]; then terom@569: log_skip "$msg: skipped" terom@569: terom@569: elif [ ! -r $RNDC_KEY ]; then terom@569: log_error " $msg: rndc: permission denied: $RNDC_KEY" terom@567: terom@567: else terom@569: log_update "$msg..." terom@567: terom@567: # run terom@567: indent " rndc: " \ terom@567: $RNDC reload terom@567: fi terom@550: } terom@567: ## Commit changes in $DATA to version control: terom@567: # terom@567: # commit_data terom@567: # terom@567: # Invokes `hg commit` in the $REPO, first showing the diff. terom@551: function commit_data { terom@562: local repo=$REPO terom@567: local commit_msg="$COMMIT_MSG" terom@544: terom@569: local msg="Commit changes in $repo" terom@544: terom@567: # operate? terom@567: if [ $COMMIT_FORCE ]; then terom@567: log_force "$msg..." terom@567: terom@567: do_commit "$commit_msg" terom@567: terom@567: elif ! hg_modified; then terom@567: log_skip "$msg: no changes" terom@567: terom@567: elif [ $COMMIT_SKIP ]; then terom@567: log_noop "$msg: skipped" terom@567: terom@544: else terom@571: log_update "$msg..." terom@567: terom@567: do_commit "$commit_msg" terom@544: fi terom@544: } terom@544: terom@567: ## Site settings, used as arguments to scripts terom@567: # MX record to generate in hosts --forward-zone terom@567: FORWARD_MX=mail terom@530: terom@567: # IP network to generate reverse records for in --reverse-zone terom@567: REVERSE_ZONE=194.197.235 terom@561: terom@567: # Origin domain to generate reverse records for in --reverse-zone terom@567: REVERSE_DOMAIN=paivola.fi terom@551: terom@567: # Views used terom@567: VIEWS=(internal external) terom@567: terom@567: # Base domain zone for domains terom@567: DOMAIN_BASE=paivola terom@567: terom@567: # List of actual domains used; will be linked to $DOMAIN_BASE terom@567: DOMAINS=(paivola.fi paivola.net paivola.org paivola.info paivola.mobi xn--pivl-load8j.fi) terom@567: terom@567: ## Operate! terom@567: function run { terom@567: ## Hosts terom@550: # test terom@536: log "Testing hosts..." terom@567: # data args... terom@567: check_hosts $DATA/paivola.txt --check-exempt ufc terom@530: terom@550: # update terom@530: log "Generating host zones..." terom@567: # hosts data args... terom@561: update_hosts $ZONES/hosts/paivola:internal $DATA/paivola.txt --forward-zone --forward-txt --forward-mx $FORWARD_MX terom@561: update_hosts $ZONES/hosts/paivola:external $DATA/paivola.txt --forward-zone terom@561: update_hosts $ZONES/hosts/194.197.235 $DATA/paivola.txt --reverse-zone $REVERSE_ZONE --reverse-domain $REVERSE_DOMAIN terom@559: terom@559: terom@561: update_hosts $ZONES/hosts/10 $DATA/pvl.txt --reverse-zone 10 --reverse-domain pvl -q terom@561: update_hosts $ZONES/hosts/192.168 $DATA/pvl.txt --reverse-zone 192.168 --reverse-domain pvl -q terom@559: terom@561: # XXX: unsupported --forward-zone with pvl.txt terom@561: # update_hosts $ZONES/hosts/pvl $DATA/pvl.txt --forward-zone terom@561: copy_hosts $ZONES/hosts/pvl $DATA/pvl.txt terom@525: terom@567: ## Includes terom@561: log "Copying zone includes..." terom@561: # view zone base terom@561: copy_zone includes paivola:internal paivola.zone.internal terom@561: copy_zone includes paivola:external paivola.zone.external terom@561: copy_zone includes paivola.auto paivola.zone.auto terom@561: copy_zone includes paivola.services paivola.zone.services terom@525: terom@567: ## Serials terom@565: log "Updating serials..." terom@541: terom@567: # zone deps... terom@568: # includes... terom@568: update_serial pvl $ZONES/hosts/pvl $DATA/pvl.zone terom@568: update_serial 10 $ZONES/hosts/10 $DATA/10.zone terom@568: update_serial 192.168 $ZONES/hosts/192.168 $DATA/192.168.zone terom@559: terom@568: update_serial paivola $ZONES/hosts/paivola:* $DATA/paivola.zone \ terom@567: $ZONES/includes/paivola:* \ terom@567: $ZONES/includes/paivola.* terom@565: terom@568: update_serial 194.197.235 $ZONES/hosts/194.197.235 $DATA/194.197.235.zone terom@536: terom@567: ## Zones terom@561: log "Updating zones..." terom@561: # view zone base terom@561: update_zone internal pvl terom@561: update_zone internal paivola terom@561: update_zone external paivola terom@533: terom@561: update_zone internal 10 terom@561: update_zone internal 192.168 terom@559: terom@561: update_zone common 194.197.235 terom@561: link_zone internal 194.197.235 terom@561: link_zone external 194.197.235 terom@559: terom@567: ## Test terom@533: log "Testing zones..." terom@561: # view zone origin terom@561: check_zone internal paivola paivola.fi terom@561: check_zone external paivola paivola.fi terom@559: terom@561: check_zone internal 10 10.in-addr.arpa terom@561: check_zone internal 192.168 192.168.in-addr.arpa terom@561: check_zone common 194.197.235 235.197.194.in-addr.arpa terom@533: terom@567: ## Domains... terom@567: log "Linking domains..." terom@567: for view in "${VIEWS[@]}"; do terom@567: for zone in "${DOMAINS[@]}"; do terom@567: # link terom@567: link_zone $view $zone $DOMAIN_BASE terom@553: terom@567: # test terom@567: check_zone $view $zone $zone terom@567: done terom@553: done terom@567: terom@567: ## Deploy terom@567: log "Deploy zones..." terom@567: deploy_zones terom@567: terom@567: ## Commit terom@567: log "Commit data..." terom@567: commit_data terom@567: } terom@567: terom@567: ## Main entry point terom@567: function main { terom@567: # test tty terom@567: [ -t 1 ] && IS_TTY=y terom@567: terom@567: parse_args "$@" terom@567: terom@567: ## test env terom@567: [ -d $ROOT/$DATA ] || die "Missing data: $ROOT/$DATA" terom@567: ensure_dir $ZONES terom@567: terom@567: ## Output dirs terom@567: for dir in "common" "hosts" "includes" "${VIEWS[@]}"; do terom@567: ensure_dir $ZONES/$dir terom@553: done terom@553: terom@567: ## Go terom@567: run terom@525: } terom@525: terom@530: main "$@"