mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-04-26 10:31:17 +00:00
349 lines
10 KiB
Bash
Executable file
349 lines
10 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
#
|
|
# Smoke tests for the top-level server installer.
|
|
|
|
set -euo pipefail
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
INSTALL_SCRIPT="${ROOT_DIR}/install.sh"
|
|
|
|
if [[ ! -f "${INSTALL_SCRIPT}" ]]; then
|
|
echo "install.sh not found at ${INSTALL_SCRIPT}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
failures=0
|
|
|
|
assert_success() {
|
|
local desc="$1"
|
|
shift
|
|
if "$@"; then
|
|
echo "[PASS] ${desc}"
|
|
return 0
|
|
else
|
|
echo "[FAIL] ${desc}" >&2
|
|
((failures++))
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
load_installer() {
|
|
# shellcheck disable=SC1090
|
|
source "${INSTALL_SCRIPT}"
|
|
trap - EXIT
|
|
}
|
|
|
|
test_infer_release_from_archive_name_supports_prerelease() {
|
|
(
|
|
load_installer
|
|
local version
|
|
version="$(infer_release_from_archive_name "/tmp/pulse-v5.1.27-rc.1-linux-arm64.tar.gz")"
|
|
[[ "${version}" == "v5.1.27-rc.1" ]]
|
|
)
|
|
}
|
|
|
|
test_ensure_update_disk_headroom_fails_when_tmp_and_install_share_full_filesystem() {
|
|
(
|
|
load_installer
|
|
|
|
UPDATE_MIN_TEMP_FREE_BYTES=$((100 * 1024))
|
|
UPDATE_MIN_INSTALL_FREE_BYTES=$((80 * 1024))
|
|
|
|
print_error() { :; }
|
|
print_info() { :; }
|
|
print_warn() { :; }
|
|
df() {
|
|
if [[ "$1" == "-Pk" ]]; then
|
|
case "$2" in
|
|
/tmp|/opt/pulse)
|
|
printf 'Filesystem 1024-blocks Used Available Capacity Mounted on\n'
|
|
printf '/dev/shared 1000 0 150 0%% /\n'
|
|
return 0
|
|
;;
|
|
esac
|
|
fi
|
|
command df "$@"
|
|
}
|
|
|
|
if ensure_update_disk_headroom /tmp /opt/pulse; then
|
|
echo "ensure_update_disk_headroom unexpectedly passed on a shared full filesystem" >&2
|
|
return 1
|
|
fi
|
|
)
|
|
}
|
|
|
|
test_ensure_update_disk_headroom_accepts_separate_filesystems_with_sufficient_space() {
|
|
(
|
|
load_installer
|
|
|
|
UPDATE_MIN_TEMP_FREE_BYTES=$((100 * 1024))
|
|
UPDATE_MIN_INSTALL_FREE_BYTES=$((80 * 1024))
|
|
|
|
print_error() { :; }
|
|
print_info() { :; }
|
|
print_warn() { :; }
|
|
df() {
|
|
if [[ "$1" == "-Pk" ]]; then
|
|
case "$2" in
|
|
/tmp)
|
|
printf 'Filesystem 1024-blocks Used Available Capacity Mounted on\n'
|
|
printf '/dev/tmp 1000 0 120 0%% /tmp\n'
|
|
return 0
|
|
;;
|
|
/opt/pulse)
|
|
printf 'Filesystem 1024-blocks Used Available Capacity Mounted on\n'
|
|
printf '/dev/root 1000 0 90 0%% /\n'
|
|
return 0
|
|
;;
|
|
esac
|
|
fi
|
|
command df "$@"
|
|
}
|
|
|
|
ensure_update_disk_headroom /tmp /opt/pulse
|
|
)
|
|
}
|
|
|
|
test_download_pulse_installs_from_local_archive_without_network() {
|
|
(
|
|
load_installer
|
|
|
|
local tmpdir archive_root archive_path
|
|
tmpdir="$(mktemp -d)"
|
|
archive_root="${tmpdir}/archive"
|
|
archive_path="${tmpdir}/pulse-v5.1.99-linux-amd64.tar.gz"
|
|
|
|
mkdir -p "${archive_root}/bin"
|
|
cat > "${archive_root}/bin/pulse" <<'EOF'
|
|
#!/usr/bin/env bash
|
|
echo "v5.1.99"
|
|
EOF
|
|
chmod +x "${archive_root}/bin/pulse"
|
|
printf 'v5.1.99\n' > "${archive_root}/VERSION"
|
|
tar -czf "${archive_path}" -C "${archive_root}" .
|
|
|
|
INSTALL_DIR="${tmpdir}/opt/pulse"
|
|
CONFIG_DIR="${tmpdir}/etc/pulse"
|
|
BUILD_FROM_SOURCE=false
|
|
SKIP_DOWNLOAD=false
|
|
ARCHIVE_OVERRIDE="${archive_path}"
|
|
FORCE_VERSION=""
|
|
FORCE_CHANNEL=""
|
|
UPDATE_CHANNEL="stable"
|
|
LATEST_RELEASE=""
|
|
STOPPED_PULSE_SERVICE=""
|
|
|
|
mkdir -p "${INSTALL_DIR}/bin" "${CONFIG_DIR}"
|
|
|
|
detect_service_name() { echo "pulse"; }
|
|
stop_pulse_service_for_update() { return 0; }
|
|
restore_selinux_contexts() { :; }
|
|
install_additional_agent_binaries() { return 0; }
|
|
deploy_agent_scripts() { return 0; }
|
|
validate_pulse_binary_architecture() { return 0; }
|
|
chown() { :; }
|
|
ln() { :; }
|
|
curl() { echo "unexpected curl call" >&2; return 99; }
|
|
wget() { echo "unexpected wget call" >&2; return 99; }
|
|
|
|
download_pulse
|
|
|
|
[[ -x "${INSTALL_DIR}/bin/pulse" ]]
|
|
[[ "$("${INSTALL_DIR}/bin/pulse" --version)" == "v5.1.99" ]]
|
|
[[ "${LATEST_RELEASE}" == "v5.1.99" ]]
|
|
)
|
|
}
|
|
|
|
test_prefetch_pulse_archive_for_container_sets_output_var() {
|
|
(
|
|
load_installer
|
|
|
|
local archive_path=""
|
|
LATEST_RELEASE="v5.1.42"
|
|
|
|
resolve_target_release() { :; }
|
|
download_release_archive() {
|
|
printf 'test archive\n' > "$3"
|
|
return 0
|
|
}
|
|
uname() { echo "x86_64"; }
|
|
|
|
prefetch_pulse_archive_for_container archive_path
|
|
|
|
[[ "${archive_path}" == /tmp/pulse-v5.1.42-amd64-lxc-*.tar.gz ]]
|
|
[[ -f "${archive_path}" ]]
|
|
rm -f "${archive_path}"
|
|
)
|
|
}
|
|
|
|
test_install_pulse_archive_rejects_mismatched_arch_without_replacing_existing_binary() {
|
|
(
|
|
load_installer
|
|
|
|
local tmpdir archive_root archive_path
|
|
tmpdir="$(mktemp -d)"
|
|
archive_root="${tmpdir}/archive"
|
|
archive_path="${tmpdir}/pulse-v5.1.99-linux-arm64.tar.gz"
|
|
|
|
mkdir -p "${archive_root}/bin"
|
|
cat > "${archive_root}/bin/pulse" <<'EOF'
|
|
#!/usr/bin/env bash
|
|
echo "v5.1.99"
|
|
EOF
|
|
chmod +x "${archive_root}/bin/pulse"
|
|
tar -czf "${archive_path}" -C "${archive_root}" .
|
|
|
|
INSTALL_DIR="${tmpdir}/opt/pulse"
|
|
mkdir -p "${INSTALL_DIR}/bin"
|
|
cat > "${INSTALL_DIR}/bin/pulse" <<'EOF'
|
|
#!/usr/bin/env bash
|
|
echo "v5.1.10"
|
|
EOF
|
|
chmod +x "${INSTALL_DIR}/bin/pulse"
|
|
|
|
validate_pulse_binary_architecture() { return 1; }
|
|
|
|
if install_pulse_archive "${archive_path}" "v5.1.99"; then
|
|
echo "install_pulse_archive unexpectedly succeeded on mismatched archive" >&2
|
|
rm -rf "${tmpdir}"
|
|
return 1
|
|
fi
|
|
|
|
[[ "$("${INSTALL_DIR}/bin/pulse" --version)" == "v5.1.10" ]]
|
|
[[ ! -e "${INSTALL_DIR}/bin/pulse.old" ]]
|
|
rm -rf "${tmpdir}"
|
|
)
|
|
}
|
|
|
|
test_parse_args_rejects_archive_with_source() {
|
|
local tmpdir output_file
|
|
tmpdir="$(mktemp -d)"
|
|
output_file="${tmpdir}/output.txt"
|
|
|
|
if bash "${INSTALL_SCRIPT}" --source --archive /tmp/pulse.tar.gz >"${output_file}" 2>&1; then
|
|
echo "installer unexpectedly accepted --archive with --source" >&2
|
|
rm -rf "${tmpdir}"
|
|
return 1
|
|
fi
|
|
|
|
if ! grep -q -- "--archive cannot be used with --source" "${output_file}"; then
|
|
echo "expected archive/source validation message" >&2
|
|
cat "${output_file}" >&2
|
|
rm -rf "${tmpdir}"
|
|
return 1
|
|
fi
|
|
|
|
rm -rf "${tmpdir}"
|
|
return 0
|
|
}
|
|
|
|
test_installer_runs_when_streamed_over_stdin() {
|
|
local tmpdir output_file
|
|
tmpdir="$(mktemp -d)"
|
|
output_file="${tmpdir}/output.txt"
|
|
|
|
if ! cat "${INSTALL_SCRIPT}" | bash -s -- --help >"${output_file}" 2>&1; then
|
|
echo "installer failed when streamed to bash" >&2
|
|
cat "${output_file}" >&2
|
|
rm -rf "${tmpdir}"
|
|
return 1
|
|
fi
|
|
|
|
if grep -q "BASH_SOURCE\\[0\\]: unbound variable" "${output_file}"; then
|
|
echo "installer still hit BASH_SOURCE unbound variable when streamed to bash" >&2
|
|
cat "${output_file}" >&2
|
|
rm -rf "${tmpdir}"
|
|
return 1
|
|
fi
|
|
|
|
if ! grep -q "Usage: install.sh \\[OPTIONS\\]" "${output_file}"; then
|
|
echo "expected streamed installer help to show install.sh usage" >&2
|
|
cat "${output_file}" >&2
|
|
rm -rf "${tmpdir}"
|
|
return 1
|
|
fi
|
|
|
|
rm -rf "${tmpdir}"
|
|
return 0
|
|
}
|
|
|
|
test_install_additional_agent_binaries_copies_local_binaries_without_network() {
|
|
(
|
|
load_installer
|
|
|
|
local tmpdir source_dir
|
|
tmpdir="$(mktemp -d)"
|
|
source_dir="${tmpdir}/source"
|
|
INSTALL_DIR="${tmpdir}/opt/pulse"
|
|
|
|
mkdir -p "${source_dir}/bin" "${INSTALL_DIR}/bin"
|
|
printf 'host-agent\n' > "${source_dir}/bin/pulse-host-agent-linux-arm64"
|
|
printf 'unified-agent\n' > "${source_dir}/bin/pulse-agent-linux-arm64"
|
|
chmod +x "${source_dir}/bin/pulse-host-agent-linux-arm64" "${source_dir}/bin/pulse-agent-linux-arm64"
|
|
|
|
local curl_calls=0
|
|
local wget_calls=0
|
|
|
|
chown() { :; }
|
|
curl() { curl_calls=$((curl_calls + 1)); return 99; }
|
|
wget() { wget_calls=$((wget_calls + 1)); return 99; }
|
|
|
|
install_additional_agent_binaries "v5.1.99" "${source_dir}"
|
|
|
|
[[ -x "${INSTALL_DIR}/bin/pulse-host-agent-linux-arm64" ]]
|
|
[[ -x "${INSTALL_DIR}/bin/pulse-agent-linux-arm64" ]]
|
|
[[ "${curl_calls}" -eq 0 ]]
|
|
[[ "${wget_calls}" -eq 0 ]]
|
|
|
|
rm -rf "${tmpdir}"
|
|
)
|
|
}
|
|
|
|
test_install_additional_agent_binaries_skips_network_when_local_extras_are_missing() {
|
|
(
|
|
load_installer
|
|
|
|
local tmpdir source_dir
|
|
tmpdir="$(mktemp -d)"
|
|
source_dir="${tmpdir}/source"
|
|
INSTALL_DIR="${tmpdir}/opt/pulse"
|
|
|
|
mkdir -p "${source_dir}/bin" "${INSTALL_DIR}/bin"
|
|
|
|
local curl_calls=0
|
|
local wget_calls=0
|
|
|
|
chown() { :; }
|
|
curl() { curl_calls=$((curl_calls + 1)); return 99; }
|
|
wget() { wget_calls=$((wget_calls + 1)); return 99; }
|
|
|
|
install_additional_agent_binaries "v5.1.99" "${source_dir}"
|
|
|
|
[[ "${curl_calls}" -eq 0 ]]
|
|
[[ "${wget_calls}" -eq 0 ]]
|
|
|
|
rm -rf "${tmpdir}"
|
|
)
|
|
}
|
|
|
|
main() {
|
|
assert_success "infer_release_from_archive_name parses prerelease tarballs" test_infer_release_from_archive_name_supports_prerelease
|
|
assert_success "update disk preflight fails on shared low-space filesystems" test_ensure_update_disk_headroom_fails_when_tmp_and_install_share_full_filesystem
|
|
assert_success "update disk preflight passes on separate filesystems with enough headroom" test_ensure_update_disk_headroom_accepts_separate_filesystems_with_sufficient_space
|
|
assert_success "download_pulse installs from local archive without network" test_download_pulse_installs_from_local_archive_without_network
|
|
assert_success "prefetch helper writes archive path via output variable" test_prefetch_pulse_archive_for_container_sets_output_var
|
|
assert_success "wrong-arch archives fail before replacing the installed binary" test_install_pulse_archive_rejects_mismatched_arch_without_replacing_existing_binary
|
|
assert_success "parse_args rejects archive with source builds" test_parse_args_rejects_archive_with_source
|
|
assert_success "installer supports curl-pipe execution via bash stdin" test_installer_runs_when_streamed_over_stdin
|
|
assert_success "install_additional_agent_binaries copies local extras without network" test_install_additional_agent_binaries_copies_local_binaries_without_network
|
|
assert_success "install_additional_agent_binaries skips network when extras are missing" test_install_additional_agent_binaries_skips_network_when_local_extras_are_missing
|
|
|
|
if (( failures > 0 )); then
|
|
echo "Total failures: ${failures}" >&2
|
|
return 1
|
|
fi
|
|
|
|
echo "All server installer smoke tests passed."
|
|
}
|
|
|
|
main "$@"
|