mirror of
https://github.com/octoleo/hosts.git
synced 2024-12-28 20:12:42 +00:00
Add backups
command.
`backups` provides subcommands for managing backups of the hosts file.
This commit is contained in:
parent
ada8cb6019
commit
4eed5251da
26
README.md
26
README.md
@ -46,6 +46,7 @@ A package for Arch users is also [available in the AUR](https://aur.archlinux.or
|
||||
Usage:
|
||||
hosts [<search string>]
|
||||
hosts add <ip> <hostname> [<comment>]
|
||||
hosts backups [create | [compare | delete | restore | show] <filename>]
|
||||
hosts block <hostname>...
|
||||
hosts disable (<ip> | <hostname> | <search string>)
|
||||
hosts disabled
|
||||
@ -109,6 +110,31 @@ Description:
|
||||
Add a given IP address and hostname pair, along with an optional comment.
|
||||
```
|
||||
|
||||
### `hosts backups`
|
||||
|
||||
```text
|
||||
Usage:
|
||||
hosts backups
|
||||
hosts backups create
|
||||
hosts backups compare <name>
|
||||
hosts backups delete <name>
|
||||
hosts backups restore <name> --skip-backup
|
||||
hosts backups show <name>
|
||||
|
||||
Subcommands:
|
||||
backups List available backups.
|
||||
backups create Create a new backup of the hosts file.
|
||||
backups compare Compare a backup file with the current hosts file.
|
||||
The diff tool configured for git will be used if
|
||||
one is set.
|
||||
backups delete Delete the specified backup.
|
||||
backups restore Replace the contents of the hosts file with a
|
||||
specified backup. The hosts file is automatically
|
||||
backed up before being overwritten unless the
|
||||
'--skip-backup' flag is specified.
|
||||
backups show Show the contents of the specified backup file.
|
||||
```
|
||||
|
||||
### `hosts block`
|
||||
|
||||
```text
|
||||
|
145
hosts
145
hosts
@ -611,6 +611,7 @@ Version: ${_VERSION}
|
||||
Usage:
|
||||
${_ME} [<search string>]
|
||||
${_ME} add <ip> <hostname> [<comment>]
|
||||
${_ME} backups [create | [compare | delete | restore | show] <filename>]
|
||||
${_ME} block <hostname>...
|
||||
${_ME} disable (<ip> | <hostname> | <search string>)
|
||||
${_ME} disabled
|
||||
@ -634,8 +635,6 @@ Options:
|
||||
|
||||
Help:
|
||||
${_ME} help [<command>]
|
||||
|
||||
$(commands)
|
||||
HEREDOC
|
||||
fi
|
||||
}
|
||||
@ -750,6 +749,148 @@ add() {
|
||||
fi
|
||||
}
|
||||
|
||||
# --------------------------------------------------------------------- backups
|
||||
|
||||
desc "backups" <<HEREDOC
|
||||
Usage:
|
||||
${_ME} backups
|
||||
${_ME} backups create
|
||||
${_ME} backups compare <name>
|
||||
${_ME} backups delete <name>
|
||||
${_ME} backups restore <name> --skip-backup
|
||||
${_ME} backups show <name>
|
||||
|
||||
Subcommands:
|
||||
backups List available backups.
|
||||
backups create Create a new backup of the hosts file.
|
||||
backups compare Compare a backup file with the current hosts file.
|
||||
The diff tool configured for git will be used if
|
||||
one is set.
|
||||
backups delete Delete the specified backup.
|
||||
backups restore Replace the contents of the hosts file with a
|
||||
specified backup. The hosts file is automatically
|
||||
backed up before being overwritten unless the
|
||||
'--skip-backup' flag is specified.
|
||||
backups show Show the contents of the specified backup file.
|
||||
HEREDOC
|
||||
backups() {
|
||||
local _subcommand="${1:-}"
|
||||
shift
|
||||
|
||||
local _hosts_dirname
|
||||
_hosts_dirname="$(dirname "${HOSTS_PATH}")"
|
||||
|
||||
case "${_subcommand}" in
|
||||
create)
|
||||
_verify_write_permissions "$@"
|
||||
|
||||
local _timestamp
|
||||
_timestamp="$(date +"%Y%m%d%H%M%S")"
|
||||
|
||||
cp "${HOSTS_PATH}" "${HOSTS_PATH}--backup-${_timestamp}" && \
|
||||
printf "Backed up to %s--backup-%s\n" "${HOSTS_PATH}" "${_timestamp}"
|
||||
;;
|
||||
compare)
|
||||
if [[ -z "${1:-}" ]]
|
||||
then
|
||||
"$_ME" help backups
|
||||
exit 1
|
||||
elif [[ ! -e "${_hosts_dirname}/${1}" ]]
|
||||
then
|
||||
printf "Backup not found: %s\n" "${1:-}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local _difftool="diff"
|
||||
if command -v git &>/dev/null
|
||||
then
|
||||
_difftool="$(git config --get merge.tool)"
|
||||
fi
|
||||
|
||||
"${_difftool}" "${HOSTS_PATH}" "${_hosts_dirname}/${1}"
|
||||
;;
|
||||
delete)
|
||||
if [[ -z "${1:-}" ]]
|
||||
then
|
||||
"$_ME" help backups
|
||||
exit 1
|
||||
fi
|
||||
|
||||
_verify_write_permissions "$@"
|
||||
|
||||
if [[ "${HOSTS_PATH}" != "${_hosts_dirname}/${1:-}" ]] &&
|
||||
[[ -e "${_hosts_dirname}/${1:-}" ]]
|
||||
then
|
||||
rm "${_hosts_dirname}/${1:-}" &&
|
||||
printf "Backup deleted: %s\n" "${_hosts_dirname}/${1:-}"
|
||||
else
|
||||
printf "Backup not found: %s\n" "${1:-}"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
restore)
|
||||
if [[ -z "${1:-}" ]]
|
||||
then
|
||||
"$_ME" help backups
|
||||
exit 1
|
||||
elif [[ ! -e "${_hosts_dirname}/${1}" ]]
|
||||
then
|
||||
printf "Backup not found: %s\n" "${1:-}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
_verify_write_permissions "$@"
|
||||
|
||||
if [[ "${2:-}" != "--skip-backup" ]]
|
||||
then
|
||||
"${_ME}" backups create
|
||||
fi
|
||||
|
||||
cat "${_hosts_dirname}/${1}" > "${HOSTS_PATH}" &&
|
||||
printf "Restored from backup: %s\n" "${1}"
|
||||
;;
|
||||
show)
|
||||
if [[ -z "${1:-}" ]]
|
||||
then
|
||||
"$_ME" help backups
|
||||
exit 1
|
||||
elif [[ ! -e "${_hosts_dirname}/${1}" ]]
|
||||
then
|
||||
printf "Backup not found: %s\n" "${1:-}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
less "${_hosts_dirname}/${1:-}"
|
||||
;;
|
||||
*)
|
||||
local _filenames=()
|
||||
|
||||
set +f
|
||||
for __filename in $(cd "${_hosts_dirname}" && ls -1 hosts* 2> /dev/null)
|
||||
do
|
||||
if [[ "${__filename:-}" != "hosts" ]] && \
|
||||
[[ ! "${__filename:-}" =~ ^hosts_test..{6}$ ]]
|
||||
then
|
||||
_filenames+=("${__filename:-}")
|
||||
fi
|
||||
done
|
||||
set -f
|
||||
|
||||
if ((${#_filenames[@]}))
|
||||
then
|
||||
for __filename in "${_filenames[@]:-}"
|
||||
do
|
||||
printf "%s\n" "${__filename}"
|
||||
done
|
||||
else
|
||||
printf \
|
||||
"No backups found. Create a new backup:\n %s backups create\n" \
|
||||
"${_ME}"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# ----------------------------------------------------------------------- block
|
||||
|
||||
desc "block" <<HEREDOC
|
||||
|
233
test/backups.bats
Executable file
233
test/backups.bats
Executable file
@ -0,0 +1,233 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
# `hosts backups` #############################################################
|
||||
|
||||
@test "\`backups\` with no backups and no arguments exits with status 0." {
|
||||
run "${_HOSTS}" backups
|
||||
printf "\${status}: %s\\n" "${status}"
|
||||
printf "\${output}: '%s'\\n" "${output}"
|
||||
[[ ${status} -eq 0 ]]
|
||||
}
|
||||
|
||||
@test "\`backups\` with backups and no arguments exits with status 0." {
|
||||
{
|
||||
run "${_HOSTS}" backups create
|
||||
}
|
||||
|
||||
run "${_HOSTS}" backups
|
||||
printf "\${status}: %s\\n" "${status}"
|
||||
printf "\${output}: '%s'\\n" "${output}"
|
||||
[[ ${status} -eq 0 ]]
|
||||
}
|
||||
|
||||
@test "\`backups\` with no backups and no arguments prints message." {
|
||||
run "${_HOSTS}" backups
|
||||
printf "\${status}: %s\\n" "${status}"
|
||||
printf "\${output}: '%s'\\n" "${output}"
|
||||
_expected="\
|
||||
No backups found. Create a new backup:
|
||||
hosts backups create"
|
||||
[[ "${output}" == "${_expected}" ]]
|
||||
}
|
||||
|
||||
@test "\`backups\` with backups and no arguments prints list of backups." {
|
||||
{
|
||||
run "${_HOSTS}" backups create
|
||||
sleep 1
|
||||
run "${_HOSTS}" backups create
|
||||
}
|
||||
|
||||
run "${_HOSTS}" backups
|
||||
printf "\${status}: %s\\n" "${status}"
|
||||
printf "\${output}: '%s'\\n" "${output}"
|
||||
[[ "${lines[0]}" =~ hosts_test ]]
|
||||
[[ "${lines[0]}" =~ '--backup-' ]]
|
||||
[[ "${lines[1]}" =~ hosts_test ]]
|
||||
[[ "${lines[1]}" =~ '--backup-' ]]
|
||||
}
|
||||
|
||||
# `hosts backups create` ######################################################
|
||||
|
||||
@test "\`backups create\` exits with status 0." {
|
||||
run "${_HOSTS}" backups create
|
||||
printf "\${status}: %s\\n" "${status}"
|
||||
printf "\${output}: '%s'\\n" "${output}"
|
||||
[[ ${status} -eq 0 ]]
|
||||
}
|
||||
|
||||
@test "\`backups create\` creates backup." {
|
||||
run "${_HOSTS}" backups create
|
||||
printf "\${status}: %s\\n" "${status}"
|
||||
printf "\${output}: '%s'\\n" "${output}"
|
||||
_backup_path="$(echo "${output}" | sed -e 's/.*\(\/tmp.*\)/\1/')"
|
||||
printf "\${_backup_path}: '%s'\\n" "${_backup_path}"
|
||||
[[ -e "${_backup_path}" ]]
|
||||
}
|
||||
|
||||
@test "\`backups create\` prints message." {
|
||||
run "${_HOSTS}" backups create
|
||||
printf "\${status}: %s\\n" "${status}"
|
||||
printf "\${output}: '%s'\\n" "${output}"
|
||||
[[ ${output} =~ 'Backed up to' ]]
|
||||
}
|
||||
|
||||
# `hosts backups compare` #####################################################
|
||||
|
||||
@test "\`backups compare\` with valid backup exits with status 0 and prints." {
|
||||
{
|
||||
run "${_HOSTS}" backups create
|
||||
_backup_path="$(echo "${output}" | sed -e 's/.*\(\/tmp.*\)/\1/')"
|
||||
_backup_basename="$(basename "${_backup_path}")"
|
||||
}
|
||||
|
||||
run "${_HOSTS}" backups show "${_backup_basename}"
|
||||
printf "\${output}: '%s'\\n" "${output}"
|
||||
printf "\${lines[6]}: '%s'\\n" "${lines[6]}"
|
||||
[[ ${status} -eq 0 ]]
|
||||
[[ "${lines[6]}" == '127.0.0.1 localhost' ]]
|
||||
}
|
||||
|
||||
@test "\`backups compare\` with invalid backup exits with status 1" {
|
||||
{
|
||||
run "${_HOSTS}" backups create
|
||||
_backup_path="$(echo "${output}" | sed -e 's/.*\(\/tmp.*\)/\1/')"
|
||||
_backup_basename="$(basename "${_backup_path}")"
|
||||
}
|
||||
|
||||
run "${_HOSTS}" backups compare "invalid-backup-name"
|
||||
printf "\${status}: %s\\n" "${status}"
|
||||
printf "\${output}: '%s'\\n" "${output}"
|
||||
[[ ${status} -eq 1 ]]
|
||||
[[ ${output} =~ 'Backup not found' ]]
|
||||
}
|
||||
|
||||
# `hosts backups delete` ######################################################
|
||||
|
||||
@test "\`backups delete\` with valid backup exits with status 0 and deletes backup" {
|
||||
{
|
||||
run "${_HOSTS}" backups create
|
||||
_backup_path="$(echo "${output}" | sed -e 's/.*\(\/tmp.*\)/\1/')"
|
||||
_backup_basename="$(basename "${_backup_path}")"
|
||||
}
|
||||
|
||||
run "${_HOSTS}" backups delete "${_backup_basename}"
|
||||
printf "\${status}: %s\\n" "${status}"
|
||||
printf "\${output}: '%s'\\n" "${output}"
|
||||
[[ ${status} -eq 0 ]]
|
||||
[[ ! -e "${_backup_path}" ]]
|
||||
[[ ${output} =~ 'Backup deleted' ]]
|
||||
}
|
||||
|
||||
@test "\`backups delete\` with invalid backup exits with status 1" {
|
||||
{
|
||||
run "${_HOSTS}" backups create
|
||||
_backup_path="$(echo "${output}" | sed -e 's/.*\(\/tmp.*\)/\1/')"
|
||||
_backup_basename="$(basename "${_backup_path}")"
|
||||
}
|
||||
|
||||
run "${_HOSTS}" backups delete "invalid-backup-name"
|
||||
printf "\${status}: %s\\n" "${status}"
|
||||
printf "\${output}: '%s'\\n" "${output}"
|
||||
[[ ${status} -eq 1 ]]
|
||||
[[ -e "${_backup_path}" ]]
|
||||
[[ ${output} =~ 'Backup not found' ]]
|
||||
}
|
||||
|
||||
# `hosts backups restore` #####################################################
|
||||
|
||||
@test "\`backups restore\` with valid backup exits with status 0 and restores" {
|
||||
{
|
||||
run "${_HOSTS}" backups create
|
||||
_backup_path="$(echo "${output}" | sed -e 's/.*\(\/tmp.*\)/\1/')"
|
||||
_backup_basename="$(basename "${_backup_path}")"
|
||||
run "${_HOSTS}" add 0.0.0.0 example.com
|
||||
sleep 1
|
||||
}
|
||||
|
||||
run "${_HOSTS}" backups restore "${_backup_basename}"
|
||||
printf "\${status}: %s\\n" "${status}"
|
||||
printf "\${output}: '%s'\\n" "${output}"
|
||||
printf "\${lines[0]}: '%s'\\n" "${lines[0]}"
|
||||
[[ ${status} -eq 0 ]]
|
||||
[[ "${lines[0]}" =~ 'Backed up to' ]]
|
||||
[[ "${lines[1]}" =~ 'Restored from backup' ]]
|
||||
|
||||
_new_backup_path="$(echo "${lines[0]}" | sed -e 's/.*\(\/tmp.*\)/\1/')"
|
||||
|
||||
_new_backup_content="$(cat "${_new_backup_path}")"
|
||||
_old_backup_content="$(cat "${_backup_path}")"
|
||||
_current_content="$(cat "${HOSTS_PATH}")"
|
||||
|
||||
[[ "${_new_backup_content}" != "${_current_content}" ]]
|
||||
[[ "${_old_backup_content}" == "${_current_content}" ]]
|
||||
}
|
||||
|
||||
@test "\`backups restore --skip-backup\` with valid backup exits with status 0 and restores" {
|
||||
{
|
||||
run "${_HOSTS}" backups create
|
||||
_backup_path="$(echo "${output}" | sed -e 's/.*\(\/tmp.*\)/\1/')"
|
||||
_backup_basename="$(basename "${_backup_path}")"
|
||||
run "${_HOSTS}" add 0.0.0.0 example.com
|
||||
_replaced_content="$(cat "${HOSTS_PATH}")"
|
||||
sleep 1
|
||||
}
|
||||
|
||||
run "${_HOSTS}" backups restore "${_backup_basename}" --skip-backup
|
||||
printf "\${status}: %s\\n" "${status}"
|
||||
printf "\${output}: '%s'\\n" "${output}"
|
||||
printf "\${lines[0]}: '%s'\\n" "${lines[0]}"
|
||||
[[ ${status} -eq 0 ]]
|
||||
[[ "${lines[0]}" =~ 'Restored from backup' ]]
|
||||
|
||||
_old_backup_content="$(cat "${_backup_path}")"
|
||||
_current_content="$(cat "${HOSTS_PATH}")"
|
||||
|
||||
[[ "${_replaced_content}" != "${_current_content}" ]]
|
||||
[[ "${_old_backup_content}" == "${_current_content}" ]]
|
||||
}
|
||||
|
||||
@test "\`backups restore\` with invalid backup exits with status 1" {
|
||||
{
|
||||
run "${_HOSTS}" backups create
|
||||
_backup_path="$(echo "${output}" | sed -e 's/.*\(\/tmp.*\)/\1/')"
|
||||
_backup_basename="$(basename "${_backup_path}")"
|
||||
}
|
||||
|
||||
run "${_HOSTS}" backups restore "invalid-backup-name"
|
||||
printf "\${status}: %s\\n" "${status}"
|
||||
printf "\${output}: '%s'\\n" "${output}"
|
||||
[[ ${status} -eq 1 ]]
|
||||
[[ ${output} =~ 'Backup not found' ]]
|
||||
}
|
||||
|
||||
# `hosts backups show` ########################################################
|
||||
|
||||
@test "\`backups show\` with valid backup exits with status 0 and prints." {
|
||||
{
|
||||
run "${_HOSTS}" backups create
|
||||
_backup_path="$(echo "${output}" | sed -e 's/.*\(\/tmp.*\)/\1/')"
|
||||
_backup_basename="$(basename "${_backup_path}")"
|
||||
}
|
||||
|
||||
run "${_HOSTS}" backups show "${_backup_basename}"
|
||||
printf "\${output}: '%s'\\n" "${output}"
|
||||
printf "\${lines[6]}: '%s'\\n" "${lines[6]}"
|
||||
[[ ${status} -eq 0 ]]
|
||||
[[ "${lines[6]}" == '127.0.0.1 localhost' ]]
|
||||
}
|
||||
|
||||
@test "\`backups show\` with invalid backup exits with status 1" {
|
||||
{
|
||||
run "${_HOSTS}" backups create
|
||||
_backup_path="$(echo "${output}" | sed -e 's/.*\(\/tmp.*\)/\1/')"
|
||||
_backup_basename="$(basename "${_backup_path}")"
|
||||
}
|
||||
|
||||
run "${_HOSTS}" backups show "invalid-backup-name"
|
||||
printf "\${status}: %s\\n" "${status}"
|
||||
printf "\${output}: '%s'\\n" "${output}"
|
||||
[[ ${status} -eq 1 ]]
|
||||
[[ ${output} =~ 'Backup not found' ]]
|
||||
}
|
@ -12,8 +12,9 @@ setup() {
|
||||
# The location of the `hosts` script being tested.
|
||||
export _HOSTS="${BATS_TEST_DIRNAME}/../hosts"
|
||||
|
||||
export _HOSTS_TEMP_DIR="/tmp"
|
||||
export _HOSTS_TEMP_PATH
|
||||
_HOSTS_TEMP_PATH="$(mktemp /tmp/hosts_test.XXXXXX)" || exit 1
|
||||
_HOSTS_TEMP_PATH="$(mktemp ${_HOSTS_TEMP_DIR}/hosts_test.XXXXXX)" || exit 1
|
||||
cat "${BATS_TEST_DIRNAME}/fixtures/hosts" > "${_HOSTS_TEMP_PATH}"
|
||||
|
||||
export HOSTS_PATH="${_HOSTS_TEMP_PATH}"
|
||||
@ -24,7 +25,7 @@ teardown() {
|
||||
[[ -e "${_HOSTS_TEMP_PATH}" ]] &&
|
||||
[[ "${_HOSTS_TEMP_PATH}" =~ ^/tmp/hosts_test ]]
|
||||
then
|
||||
rm "${_HOSTS_TEMP_PATH}"
|
||||
rm -f "${_HOSTS_TEMP_DIR}"/hosts_test.*
|
||||
fi
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user