Pulse/scripts/installtests/uninstall_sensor_proxy_test.go
rcourtman bd6f77e093 Prepare v6.0.0 release candidate
Tighten v5-to-v6 upgrade safety, release installability, provider MSP mode handling, AI cost accounting, metrics flushing, and frontend guardrails for the v6.0.0 GA candidate.
2026-06-04 14:07:14 +01:00

119 lines
4.2 KiB
Go

package installtests
import (
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
)
func TestUninstallSensorProxyScriptContract(t *testing.T) {
scriptPath := repoFile("scripts", "uninstall-sensor-proxy.sh")
content, err := os.ReadFile(scriptPath)
if err != nil {
t.Fatalf("read uninstall-sensor-proxy.sh: %v", err)
}
script := string(content)
required := []string{
`--remove-proxmox-access`,
`pulse-sensor-proxy-selfheal.timer`,
`pulse-sensor-cleanup.path`,
`remove_managed_keys_from_authorized_keys_file()`,
`cleanup_stale_sensor_proxy_mounts()`,
`pulse-monitor@pam`,
`# pulse-(managed|proxy)-key$`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("uninstall-sensor-proxy.sh missing cleanup contract: %s", needle)
}
}
if out, err := exec.Command("bash", "-n", scriptPath).CombinedOutput(); err != nil {
t.Fatalf("bash -n uninstall-sensor-proxy.sh: %v\n%s", err, out)
}
}
func TestUninstallSensorProxyScriptRemovesTempFootprintAndManagedKeys(t *testing.T) {
tmpDir := t.TempDir()
binDir := filepath.Join(tmpDir, "bin")
if err := os.MkdirAll(binDir, 0755); err != nil {
t.Fatalf("mkdir bin dir: %v", err)
}
if err := os.WriteFile(filepath.Join(binDir, "systemctl"), []byte("#!/bin/sh\nexit 0\n"), 0755); err != nil {
t.Fatalf("write systemctl stub: %v", err)
}
if err := os.WriteFile(filepath.Join(binDir, "pct"), []byte("#!/bin/sh\nexit 0\n"), 0755); err != nil {
t.Fatalf("write pct stub: %v", err)
}
binaryPath := filepath.Join(tmpDir, "pulse-sensor-proxy")
installRoot := filepath.Join(tmpDir, "install-root")
servicePath := filepath.Join(tmpDir, "pulse-sensor-proxy.service")
runtimeDir := filepath.Join(tmpDir, "run")
socketPath := filepath.Join(runtimeDir, "pulse-sensor-proxy.sock")
workDir := filepath.Join(tmpDir, "work")
configDir := filepath.Join(tmpDir, "config")
logDir := filepath.Join(tmpDir, "logs")
authKeys := filepath.Join(tmpDir, "authorized_keys")
for _, dir := range []string{installRoot, runtimeDir, workDir, configDir, logDir} {
if err := os.MkdirAll(dir, 0755); err != nil {
t.Fatalf("mkdir %s: %v", dir, err)
}
}
for _, path := range []string{binaryPath, servicePath, socketPath, filepath.Join(installRoot, "bin", "pulse-sensor-proxy")} {
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
t.Fatalf("mkdir parent for %s: %v", path, err)
}
if err := os.WriteFile(path, []byte("legacy"), 0644); err != nil {
t.Fatalf("write %s: %v", path, err)
}
}
if err := os.WriteFile(authKeys, []byte(strings.Join([]string{
"ssh-ed25519 AAAAlegacy1 pulse # pulse-managed-key",
"ssh-ed25519 AAAAkeep user-key",
"ssh-ed25519 AAAAlegacy2 pulse # pulse-proxy-key",
"",
}, "\n")), 0600); err != nil {
t.Fatalf("write authorized_keys: %v", err)
}
cmd := exec.Command("bash", repoFile("scripts", "uninstall-sensor-proxy.sh"), "--uninstall", "--purge", "--quiet")
cmd.Env = append(os.Environ(),
"PATH="+binDir+string(os.PathListSeparator)+os.Getenv("PATH"),
"PULSE_SENSOR_PROXY_BINARY_PATH="+binaryPath,
"PULSE_SENSOR_PROXY_INSTALL_ROOT="+installRoot,
"PULSE_SENSOR_PROXY_SERVICE_PATH="+servicePath,
"PULSE_SENSOR_PROXY_RUNTIME_DIR="+runtimeDir,
"PULSE_SENSOR_PROXY_SOCKET_PATH="+socketPath,
"PULSE_SENSOR_PROXY_WORK_DIR="+workDir,
"PULSE_SENSOR_PROXY_CONFIG_DIR="+configDir,
"PULSE_SENSOR_PROXY_LOG_DIR="+logDir,
"PULSE_SENSOR_PROXY_SERVICE_USER=pulse-sensor-proxy-test-user",
"PULSE_SENSOR_PROXY_AUTHORIZED_KEYS_PATH="+authKeys,
)
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("uninstall-sensor-proxy.sh failed: %v\n%s", err, out)
}
for _, path := range []string{binaryPath, installRoot, servicePath, runtimeDir, workDir, configDir, logDir} {
if _, err := os.Stat(path); !os.IsNotExist(err) {
t.Fatalf("expected %s to be removed, stat err=%v", path, err)
}
}
content, err := os.ReadFile(authKeys)
if err != nil {
t.Fatalf("read authorized_keys: %v", err)
}
got := string(content)
if strings.Contains(got, "pulse-managed-key") || strings.Contains(got, "pulse-proxy-key") {
t.Fatalf("managed Pulse SSH keys were not removed:\n%s", got)
}
if !strings.Contains(got, "AAAAkeep") {
t.Fatalf("non-Pulse SSH key was not preserved:\n%s", got)
}
}