feat: Pulse v6 release

This commit is contained in:
rcourtman 2026-03-18 16:06:30 +00:00
parent 2fe22c3308
commit 778a2577b6
3155 changed files with 594553 additions and 173975 deletions

View file

@ -11,22 +11,6 @@ generation, binary placement).
is unavailable the test will skip gracefully.
- Internet access is **not** required; HTTP interactions are stubbed.
## Running the Docker Agent Installer Test
```bash
scripts/tests/integration/test-docker-agent-install.sh
```
The script will:
1. Launch an Ubuntu 22.04 container (when Docker is available).
2. Inject lightweight stubs for `systemctl`, `docker`, `curl`, and `wget`.
3. Execute the refactored installer through several scenarios (dry run,
full install, missing Docker handling, multi-target configuration, uninstall).
The container is discarded automatically, and no files are written to the host
outside of the repository.
## Adding New Integration Tests
1. Place new test scripts in this directory. They should follow the pattern of

View file

@ -1,277 +0,0 @@
#!/usr/bin/env bash
# Integration test for install-docker-agent-v2.sh
set -euo pipefail
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
CONTAINER_IMAGE="${INTEGRATION_DOCKER_IMAGE:-ubuntu:22.04}"
log() {
printf '[integration] %s\n' "$*"
}
if ! command -v docker >/dev/null 2>&1; then
log "Docker not available. Skipping docker-agent integration tests."
exit 0
fi
log "Running docker-agent installer integration tests in ${CONTAINER_IMAGE}"
container_script="$(mktemp -t pulse-docker-agent-integ-XXXXXX.sh)"
trap 'rm -f "${container_script}"' EXIT
cat <<'EOS' >"${container_script}"
#!/usr/bin/env bash
set -euo pipefail
INSTALLER_SCRIPT="/workspace/scripts/install-docker-agent-v2.sh"
STUB_DIR=/tmp/installer-stubs
mkdir -p "${STUB_DIR}"
create_systemctl_stub() {
cat <<'EOF' >"${STUB_DIR}/systemctl"
#!/usr/bin/env bash
set -eo pipefail
cmd=""
for arg in "$@"; do
case "$arg" in
list-unit-files|is-active|daemon-reload|enable|start|stop|disable|restart)
cmd="$arg"
shift
break
;;
esac
shift || true
done
case "$cmd" in
list-unit-files)
exit 1
;;
is-active)
unit=""
for arg in "$@"; do
case "$arg" in
--*) ;;
*) unit="$arg"; break ;;
esac
done
if [[ -n "$unit" && -f "/etc/systemd/system/$unit" ]]; then
exit 0
fi
exit 3
;;
*)
exit 0
;;
esac
EOF
chmod +x "${STUB_DIR}/systemctl"
}
create_curl_stub() {
cat <<'EOF' >"${STUB_DIR}/curl"
#!/usr/bin/env bash
set -eo pipefail
outfile=""
while [[ $# -gt 0 ]]; do
case "$1" in
-o|--output)
outfile="$2"; shift 2;;
-H|-d|-X|--header|--data|--request|--url)
shift 2;;
-f|-s|-S|-L|-k|--progress-bar|--connect-timeout|--retry|--retry-delay|--silent)
shift;;
*)
shift;;
esac
done
if [[ -n "${outfile:-}" ]]; then
cat <<'SCRIPT' >"$outfile"
#!/usr/bin/env bash
if [[ "$1" == "--help" ]]; then
echo "--no-auto-update"
fi
exit 0
SCRIPT
chmod +x "$outfile"
else
printf '{"ok":true}\n'
fi
EOF
chmod +x "${STUB_DIR}/curl"
}
create_wget_stub() {
cat <<'EOF' >"${STUB_DIR}/wget"
#!/usr/bin/env bash
set -eo pipefail
outfile=""
while [[ $# -gt 0 ]]; do
case "$1" in
-O|--output-document)
outfile="$2"; shift 2;;
--header|--method|--body-data)
shift 2;;
-q|--quiet|--show-progress|--no-check-certificate)
shift;;
*)
shift;;
esac
done
if [[ -n "${outfile:-}" ]]; then
cat <<'SCRIPT' >"$outfile"
#!/usr/bin/env bash
if [[ "$1" == "--help" ]]; then
echo "--no-auto-update"
fi
exit 0
SCRIPT
chmod +x "$outfile"
else
printf '{"ok":true}\n'
fi
EOF
chmod +x "${STUB_DIR}/wget"
}
create_docker_stub() {
cat <<'EOF' >"${STUB_DIR}/docker"
#!/usr/bin/env bash
set -eo pipefail
if [[ "${1:-}" == "info" ]]; then
if [[ "${2:-}" == "--format" ]]; then
printf 'stub-host-id\n'
else
printf '{}\n'
fi
exit 0
fi
exit 0
EOF
chmod +x "${STUB_DIR}/docker"
}
create_stubs() {
create_systemctl_stub
create_curl_stub
create_wget_stub
create_docker_stub
export PATH="${STUB_DIR}:$PATH"
}
assert_file_contains() {
local file=$1
local expected=$2
if ! grep -Fq "$expected" "$file"; then
echo "Expected to find \"$expected\" in $file" >&2
exit 1
fi
}
test_dry_run() {
echo "== Dry-run scenario =="
set +e
output="$(PULSE_FORCE_INTERACTIVE=1 PATH="${STUB_DIR}:$PATH" bash "${INSTALLER_SCRIPT}" --dry-run --url http://primary.local --token token123 2>&1)"
status=$?
set -e
if [[ $status -ne 0 ]]; then
echo "$output"
echo "dry-run failed"
exit 1
fi
if [[ "$output" != *"[dry-run]"* ]]; then
echo "$output"
echo "dry-run output missing markers"
exit 1
fi
}
test_install_basic() {
echo "== Basic installation =="
rm -f /usr/local/bin/pulse-docker-agent /etc/systemd/system/pulse-docker-agent.service
PULSE_FORCE_INTERACTIVE=1 PATH="${STUB_DIR}:$PATH" bash "${INSTALLER_SCRIPT}" --url http://primary.local --token token123 --interval 15s >/tmp/install.log 2>&1
test -f /usr/local/bin/pulse-docker-agent
test -f /etc/systemd/system/pulse-docker-agent.service
assert_file_contains /etc/systemd/system/pulse-docker-agent.service "Environment=\"PULSE_URL=http://primary.local\""
assert_file_contains /etc/systemd/system/pulse-docker-agent.service "ExecStart=/usr/local/bin/pulse-docker-agent --url \"http://primary.local\" --interval \"15s\""
}
test_install_without_docker() {
echo "== Installation without docker binary =="
mv "${STUB_DIR}/docker" "${STUB_DIR}/docker.disabled"
set +e
output="$(printf 'y\n' | PULSE_FORCE_INTERACTIVE=1 PATH="${STUB_DIR}:$PATH" bash "${INSTALLER_SCRIPT}" --dry-run --url http://nodocker.local --token token456 2>&1)"
status=${PIPESTATUS[1]:-0}
set -e
mv "${STUB_DIR}/docker.disabled" "${STUB_DIR}/docker"
if [[ $status -ne 0 ]]; then
echo "$output"
echo "dry-run without docker failed"
exit 1
fi
if [[ "$output" != *"Docker not found"* ]]; then
echo "$output"
echo "expected docker warning"
exit 1
fi
}
test_multi_target() {
echo "== Multi-target installation =="
rm -f /usr/local/bin/pulse-docker-agent /etc/systemd/system/pulse-docker-agent.service
PULSE_FORCE_INTERACTIVE=1 PATH="${STUB_DIR}:$PATH" bash "${INSTALLER_SCRIPT}" \
--url http://primary.local \
--token token789 \
--target 'https://target.one|tok1' \
--target 'https://target.two|tok2' \
>/tmp/install-multi.log 2>&1
if [[ ! -f /etc/systemd/system/pulse-docker-agent.service ]]; then
echo "ERROR: Service file doesn't exist!" >&2
exit 1
fi
echo "Service file contents:"
cat /etc/systemd/system/pulse-docker-agent.service
assert_file_contains /etc/systemd/system/pulse-docker-agent.service 'PULSE_TARGETS='
}
test_uninstall() {
echo "== Uninstall =="
PATH="${STUB_DIR}:$PATH" bash "${INSTALLER_SCRIPT}" --uninstall >/tmp/uninstall.log 2>&1
if [[ -f /etc/systemd/system/pulse-docker-agent.service ]]; then
echo "service file still present after uninstall" >&2
exit 1
fi
if [[ -f /usr/local/bin/pulse-docker-agent ]]; then
echo "agent binary still present after uninstall" >&2
exit 1
fi
}
create_stubs
test_dry_run
test_install_basic
test_install_without_docker
test_multi_target
test_uninstall
echo "All docker-agent installer integration scenarios passed."
EOS
chmod +x "${container_script}"
docker run --rm \
-v "${PROJECT_ROOT}:/workspace:ro" \
-v "${container_script}:/tmp/integration-test.sh:ro" \
-w /workspace \
"${CONTAINER_IMAGE}" \
bash /tmp/integration-test.sh
log "Integration testing complete."

View file

@ -1,85 +0,0 @@
#!/usr/bin/env bash
# Smoke tests for install-docker-agent-v2.sh
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
SCRIPT_PATH="${ROOT_DIR}/scripts/install-docker-agent-v2.sh"
TEST_NAME="install-docker-agent-v2"
if [[ ! -f "${SCRIPT_PATH}" ]]; then
echo "Missing script at ${SCRIPT_PATH}" >&2
exit 1
fi
TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/pulse-test-XXXXXX")"
trap 'rm -rf "${TMP_DIR}"' EXIT
pass_count=0
fail_count=0
log_pass() {
echo "[PASS] $1"
((pass_count++))
return 0
}
log_fail() {
echo "[FAIL] $1" >&2
((fail_count++))
return 1
}
run_test() {
local desc="$1"
shift
if "$@"; then
log_pass "$desc"
else
local status=$?
log_fail "$desc (exit ${status})"
fi
}
set +e
run_test "syntax check" bash -n "${SCRIPT_PATH}"
set -e
# Test dry-run output captures action hints
set +e
DRY_RUN_OUTPUT="$("${SCRIPT_PATH}" --dry-run --url http://test.local --token testtoken 2>&1)"
DRY_STATUS=$?
set -e
if (( DRY_STATUS == 0 )) && [[ "${DRY_RUN_OUTPUT}" == *"[dry-run]"* ]]; then
log_pass "dry-run outputs actions"
else
log_fail "dry-run outputs actions"
echo "${DRY_RUN_OUTPUT}"
fi
if (( DRY_STATUS == 0 )); then
log_pass "dry-run exits successfully"
else
log_fail "dry-run exits successfully (exit ${DRY_STATUS})"
echo "${DRY_RUN_OUTPUT}"
fi
# Test argument validation (missing token)
MISSING_TOKEN_LOG="${TMP_DIR}/missing-token.log"
set +e
"${SCRIPT_PATH}" --dry-run --url http://test.local >"${MISSING_TOKEN_LOG}" 2>&1
ARG_STATUS=$?
set -e
if (( ARG_STATUS == 0 )); then
log_fail "missing token rejected"
cat "${MISSING_TOKEN_LOG}"
else
log_pass "missing token rejected"
fi
if (( fail_count > 0 )); then
echo "${TEST_NAME}: ${fail_count} failures" >&2
exit 1
fi
echo "All ${TEST_NAME} tests passed (${pass_count})"

View file

@ -0,0 +1,182 @@
#!/usr/bin/env bash
#
# Validates repository script references:
# 1) `./scripts/*.sh` references inside tracked shell scripts resolve.
# 2) `scripts/bundle.manifest` source entries exist.
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
BUNDLE_MANIFEST="${ROOT_DIR}/scripts/bundle.manifest"
STANDALONE_MANIFEST="${ROOT_DIR}/scripts/standalone.manifest"
failures=0
declare -A STANDALONE_DECLARED=()
record_failure() {
echo "[FAIL] $1" >&2
((failures+=1))
}
record_pass() {
echo "[PASS] $1"
}
check_script_refs() {
local checked=0
local script rel_ref target
while IFS= read -r script; do
[[ -f "${script}" ]] || continue
while IFS= read -r rel_ref; do
target="${ROOT_DIR}/${rel_ref#./}"
((checked += 1))
if [[ ! -f "${target}" ]]; then
record_failure "${script#${ROOT_DIR}/}: missing referenced script ${rel_ref}"
fi
done < <(grep -Eo '\./scripts/[A-Za-z0-9_.-]+\.sh' "${script}" | sort -u || true)
done < <(git -C "${ROOT_DIR}" ls-files '*.sh' | sed "s#^#${ROOT_DIR}/#")
if (( checked == 0 )); then
record_failure "no script references scanned"
return 1
fi
if (( failures == 0 )); then
record_pass "tracked script references resolve (${checked} references scanned)"
fi
}
check_bundle_manifest() {
local checked=0
local line source_path
if [[ ! -f "${BUNDLE_MANIFEST}" ]]; then
record_failure "missing bundle manifest (${BUNDLE_MANIFEST})"
return 1
fi
while IFS= read -r line; do
[[ -z "${line}" || "${line}" =~ ^[[:space:]]*# ]] && continue
[[ "${line}" =~ ^output:[[:space:]]+ ]] && continue
source_path="${ROOT_DIR}/${line}"
((checked += 1))
if [[ ! -f "${source_path}" ]]; then
record_failure "bundle manifest entry missing: ${line}"
fi
done < "${BUNDLE_MANIFEST}"
if (( checked == 0 )); then
record_failure "bundle manifest contains no source entries"
return 1
fi
if (( failures == 0 )); then
record_pass "bundle manifest source entries resolve (${checked} entries checked)"
fi
}
load_standalone_manifest() {
local line script reason
if [[ ! -f "${STANDALONE_MANIFEST}" ]]; then
record_failure "missing standalone manifest (${STANDALONE_MANIFEST})"
return 1
fi
while IFS= read -r line; do
[[ -z "${line}" || "${line}" =~ ^[[:space:]]*# ]] && continue
if [[ "${line}" != *"|"* ]]; then
record_failure "standalone manifest malformed line: ${line}"
continue
fi
script="$(echo "${line%%|*}" | xargs)"
reason="$(echo "${line#*|}" | xargs)"
if [[ -z "${script}" || -z "${reason}" ]]; then
record_failure "standalone manifest missing script or reason: ${line}"
continue
fi
if [[ "${script}" != scripts/*.sh ]]; then
record_failure "standalone manifest entry must be scripts/*.sh: ${script}"
continue
fi
if ! git -C "${ROOT_DIR}" ls-files --error-unmatch "${script}" >/dev/null 2>&1; then
record_failure "standalone manifest entry not tracked: ${script}"
continue
fi
STANDALONE_DECLARED["${script}"]="${reason}"
done < "${STANDALONE_MANIFEST}"
if (( ${#STANDALONE_DECLARED[@]} == 0 )); then
record_failure "standalone manifest has no usable entries"
return 1
fi
}
has_external_path_reference() {
local script="$1"
local pattern result_line ref_file normalized
for pattern in "${script}" "./${script}"; do
while IFS= read -r result_line; do
ref_file="${result_line%%:*}"
normalized="${ref_file#${ROOT_DIR}/}"
normalized="${normalized#./}"
[[ "${normalized}" == "${script}" ]] && continue
[[ "${normalized}" == "scripts/standalone.manifest" ]] && continue
return 0
done < <(rg --hidden -n -F "${pattern}" "${ROOT_DIR}" --glob '!**/.git/**' || true)
done
return 1
}
check_unreferenced_scripts_are_declared() {
local script checked=0 unreferenced=0
while IFS= read -r script; do
[[ "${script}" == scripts/tests/* ]] && continue
[[ "${script}" == scripts/lib/* ]] && continue
((checked += 1))
if has_external_path_reference "${script}"; then
continue
fi
((unreferenced += 1))
if [[ -z "${STANDALONE_DECLARED[${script}]:-}" ]]; then
record_failure "unreferenced script must be declared in scripts/standalone.manifest: ${script}"
fi
done < <(git -C "${ROOT_DIR}" ls-files '*.sh' | grep '^scripts/' || true)
if (( checked == 0 )); then
record_failure "no scripts checked for standalone declaration"
return 1
fi
if (( failures == 0 )); then
record_pass "unreferenced script declaration check passed (${unreferenced} unreferenced scripts declared)"
fi
}
main() {
check_script_refs
check_bundle_manifest
load_standalone_manifest
check_unreferenced_scripts_are_declared
if (( failures > 0 )); then
echo "script reference integrity checks failed: ${failures}" >&2
exit 1
fi
echo "All script reference integrity checks passed."
}
main "$@"