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