test(proxmox): coverage uplift to ≥70% (T01.5, REQ-057)
Extend bootstrap_test.go with FullFlow_IdempotentReRun (two sequential bootstraps on the same fake SSH server — verifies the idempotent no-op path end-to-end), FullFlow_NoPasswordInLogs (asserts the SSH password never appears in slog output, D-031), FullFlow_ValidateSudoersFails (forceSudoersInvalid flag → wrapped 'validate sudoers' error), FullFlow_CreateLinuxUserFails (ProxmoxUser=root exercises the /root home branch in deployPubKey), DefaultSSHDialer_DialContext_ConnectionRefused (covers the real defaultSSHDialer.DialContext concrete path), and SSHSessionRunner_CombinedOutput_NewSessionError (closed-client → 'new session' error branch). Add forceSudoersInvalid knob + funcDialer helper to ssh_session_test.go. Coverage: 83.2% → 87.1%. go test -race PASS. No production code changed (T01.1 sessionRunner seam already in place). ---ci--- project: orca phase: 1 milestone: v0.8 status: execute ---/ci---
This commit is contained in:
@@ -5,10 +5,12 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"log/slog"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
@@ -330,3 +332,159 @@ func TestDeployPubKey_WhitespaceOnlyPubLine(t *testing.T) {
|
||||
t.Error("expected error for whitespace-only pub line")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBootstrapProxmox_FullFlow_IdempotentReRun(t *testing.T) {
|
||||
srv := newFakeSSHServer(t)
|
||||
defer srv.close()
|
||||
|
||||
home := t.TempDir()
|
||||
t.Setenv("ORCA_HOME", home)
|
||||
if err := os.WriteFile(filepath.Join(home, "known_hosts"), []byte{}, 0o600); err != nil {
|
||||
t.Fatalf("create known_hosts: %v", err)
|
||||
}
|
||||
|
||||
orig := sshDialer
|
||||
defer func() { sshDialer = orig }()
|
||||
origRunner := sessionRunner
|
||||
defer func() { sessionRunner = origRunner }()
|
||||
|
||||
host, _, _ := net.SplitHostPort(srv.addr())
|
||||
sshDialer = &funcDialer{fn: func(ctx context.Context, network, addr string, config *ssh.ClientConfig) (*ssh.Client, error) {
|
||||
return fakeSSHClient(t, srv), nil
|
||||
}}
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
sessionRunner = nil
|
||||
if _, err := BootstrapProxmox(t.Context(), Options{
|
||||
Host: host,
|
||||
Password: "pw",
|
||||
}); err != nil {
|
||||
t.Fatalf("bootstrap run %d: %v", i+1, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBootstrapProxmox_FullFlow_NoPasswordInLogs(t *testing.T) {
|
||||
srv := newFakeSSHServer(t)
|
||||
defer srv.close()
|
||||
|
||||
home := t.TempDir()
|
||||
t.Setenv("ORCA_HOME", home)
|
||||
if err := os.WriteFile(filepath.Join(home, "known_hosts"), []byte{}, 0o600); err != nil {
|
||||
t.Fatalf("create known_hosts: %v", err)
|
||||
}
|
||||
|
||||
orig := sshDialer
|
||||
defer func() { sshDialer = orig }()
|
||||
origRunner := sessionRunner
|
||||
defer func() { sessionRunner = origRunner }()
|
||||
sessionRunner = nil
|
||||
sshDialer = &staticDialer{client: fakeSSHClient(t, srv)}
|
||||
|
||||
host, _, _ := net.SplitHostPort(srv.addr())
|
||||
|
||||
var logBuf bytes.Buffer
|
||||
_, err := BootstrapProxmox(t.Context(), Options{
|
||||
Host: host,
|
||||
Password: "super-secret-pw-12345",
|
||||
Logger: slog.New(slog.NewTextHandler(&logBuf, nil)),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("BootstrapProxmox: %v", err)
|
||||
}
|
||||
out := logBuf.String()
|
||||
if strings.Contains(out, "super-secret-pw-12345") {
|
||||
t.Errorf("password leaked into logs (D-031): %s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBootstrapProxmox_FullFlow_ValidateSudoersFails(t *testing.T) {
|
||||
srv := newFakeSSHServer(t)
|
||||
defer srv.close()
|
||||
srv.forceSudoersInvalid = true
|
||||
|
||||
home := t.TempDir()
|
||||
t.Setenv("ORCA_HOME", home)
|
||||
if err := os.WriteFile(filepath.Join(home, "known_hosts"), []byte{}, 0o600); err != nil {
|
||||
t.Fatalf("create known_hosts: %v", err)
|
||||
}
|
||||
|
||||
orig := sshDialer
|
||||
defer func() { sshDialer = orig }()
|
||||
origRunner := sessionRunner
|
||||
defer func() { sessionRunner = origRunner }()
|
||||
sessionRunner = nil
|
||||
sshDialer = &staticDialer{client: fakeSSHClient(t, srv)}
|
||||
|
||||
host, _, _ := net.SplitHostPort(srv.addr())
|
||||
|
||||
_, err := BootstrapProxmox(t.Context(), Options{
|
||||
Host: host,
|
||||
Password: "pw",
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatal("expected error for invalid sudoers")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "validate sudoers") {
|
||||
t.Errorf("error should mention validate sudoers, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultSSHDialer_DialContext_ConnectionRefused(t *testing.T) {
|
||||
d := defaultSSHDialer{}
|
||||
cfg := &ssh.ClientConfig{
|
||||
User: "root",
|
||||
Auth: []ssh.AuthMethod{ssh.Password("pw")},
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
Timeout: 200 * time.Millisecond,
|
||||
}
|
||||
_, err := d.DialContext(context.Background(), "tcp", "127.0.0.1:1", cfg)
|
||||
if err == nil {
|
||||
t.Fatal("expected error for connection refused")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBootstrapProxmox_FullFlow_CreateLinuxUserFails(t *testing.T) {
|
||||
srv := newFakeSSHServer(t)
|
||||
defer srv.close()
|
||||
|
||||
home := t.TempDir()
|
||||
t.Setenv("ORCA_HOME", home)
|
||||
if err := os.WriteFile(filepath.Join(home, "known_hosts"), []byte{}, 0o600); err != nil {
|
||||
t.Fatalf("create known_hosts: %v", err)
|
||||
}
|
||||
|
||||
orig := sshDialer
|
||||
defer func() { sshDialer = orig }()
|
||||
origRunner := sessionRunner
|
||||
defer func() { sessionRunner = origRunner }()
|
||||
sessionRunner = nil
|
||||
sshDialer = &staticDialer{client: fakeSSHClient(t, srv)}
|
||||
|
||||
host, _, _ := net.SplitHostPort(srv.addr())
|
||||
|
||||
// ProxmoxUser=root exercises the /root home branch in deployPubKey.
|
||||
_, err := BootstrapProxmox(t.Context(), Options{
|
||||
Host: host,
|
||||
Password: "pw",
|
||||
ProxmoxUser: "root",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("BootstrapProxmox with ProxmoxUser=root: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSSHSessionRunner_CombinedOutput_NewSessionError(t *testing.T) {
|
||||
srv := newFakeSSHServer(t)
|
||||
defer srv.close()
|
||||
conn := fakeSSHClient(t, srv)
|
||||
conn.Close()
|
||||
r := &sshSessionRunner{client: conn}
|
||||
_, err := r.CombinedOutput("echo hi")
|
||||
if err == nil {
|
||||
t.Fatal("expected error from NewSession on closed client")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "new session") {
|
||||
t.Errorf("error should mention new session, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,10 @@ type fakeSSHServer struct {
|
||||
config *ssh.ServerConfig
|
||||
done chan struct{}
|
||||
|
||||
mu sync.Mutex
|
||||
state map[string]string
|
||||
authDir string
|
||||
mu sync.Mutex
|
||||
state map[string]string
|
||||
authDir string
|
||||
forceSudoersInvalid bool
|
||||
}
|
||||
|
||||
func newFakeSSHServer(t *testing.T) *fakeSSHServer {
|
||||
@@ -142,10 +143,11 @@ func (s *fakeSSHServer) runCommand(cmd string) ([]byte, int) {
|
||||
case strings.HasPrefix(trimmed, "cat > /etc/sudoers.d/"):
|
||||
return s.handleSudoersWrite(trimmed), 0
|
||||
case strings.HasPrefix(trimmed, "visudo -cf /etc/sudoers.d/orca"):
|
||||
if s.state["sudoers_valid"] == "true" {
|
||||
return []byte("/etc/sudoers.d/orca: parsed OK\n"), 0
|
||||
force := s.forceSudoersInvalid
|
||||
if force || s.state["sudoers_valid"] != "true" {
|
||||
return []byte("/etc/sudoers.d/orca: syntax error\n"), 1
|
||||
}
|
||||
return []byte("/etc/sudoers.d/orca: syntax error\n"), 1
|
||||
return []byte("/etc/sudoers.d/orca: parsed OK\n"), 0
|
||||
case strings.HasPrefix(trimmed, "cat /") && strings.HasSuffix(trimmed, "/authorized_keys"):
|
||||
return s.readAuthFile(trimmed[4:]), 0
|
||||
case strings.HasPrefix(trimmed, "cat /") && strings.Contains(trimmed, "/orca"):
|
||||
@@ -406,6 +408,14 @@ func (d *staticDialer) DialContext(ctx context.Context, network, addr string, co
|
||||
return d.client, nil
|
||||
}
|
||||
|
||||
type funcDialer struct {
|
||||
fn func(ctx context.Context, network, addr string, config *ssh.ClientConfig) (*ssh.Client, error)
|
||||
}
|
||||
|
||||
func (d *funcDialer) DialContext(ctx context.Context, network, addr string, config *ssh.ClientConfig) (*ssh.Client, error) {
|
||||
return d.fn(ctx, network, addr, config)
|
||||
}
|
||||
|
||||
func TestBootstrapProxmox_FullFlow_Success(t *testing.T) {
|
||||
srv := newFakeSSHServer(t)
|
||||
defer srv.close()
|
||||
|
||||
Reference in New Issue
Block a user