Simplify the KVM provider after the /simplify review

Collapse duplicated logic the review found in PR #5 without changing
behaviour: one releaseFinalizer helper for the four finalizer exits in
reconcileDelete, classify reusing isClassified and provider.Class, the
image URL check and format/firmware values shared from the provider
package, imageSource and the metadata parser embedding their config
structs instead of copying fields, and the SSH loader as a small struct
that keeps only the SSH fields and is seeded by New instead of loading
the key twice. Tracing builds its V(2)-only lists only at V(2).

Tests: drop a duplicate New test, fold near-identical tests into tables
(connection drops, metadata parsing, cached images), add mustSSHAuth,
and use wantClass where classes were checked by hand.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-11 06:24:43 +00:00
co-authored by Claude Opus 5
parent 2b4b61cdc4
commit 82eeeef9da
13 changed files with 303 additions and 376 deletions
+51 -45
View File
@@ -182,7 +182,7 @@ func awaitOrCancel(ctx context.Context, fn func() error, abort func()) error {
// sshAuth holds the pieces of the SSH client config shared by every host:
// the private key and the host-key policy. Both are loaded on the first
// connection rather than at startup — see lazyDialer.
// connection rather than at startup — see lazySSH.
type sshAuth struct {
signer ssh.Signer
hostKey ssh.HostKeyCallback
@@ -204,7 +204,7 @@ func newSSHAuth(cfg provider.KVMConfig) (*sshAuth, error) {
hostKey := ssh.InsecureIgnoreHostKey() //nolint:gosec // opt-in via config, documented as insecure
if !cfg.InsecureIgnoreHostKey {
hostKey, err = knownhosts.New(cfg.KnownHostsFile)
if err != nil && errors.Is(err, fs.ErrNotExist) {
if errors.Is(err, fs.ErrNotExist) {
return nil, fmt.Errorf("loading kvm.knownHostsFile: %w", err)
}
if err != nil {
@@ -214,58 +214,64 @@ func newSSHAuth(cfg provider.KVMConfig) (*sshAuth, error) {
return &sshAuth{signer: signer, hostKey: hostKey}, nil
}
// lazyAuth defers loading the SSH material to the first connection and
// lazySSH defers loading the SSH material until it is first needed and
// caches it once it works. The kvm-ssh Secret is an optional mount: the
// manager has to start without it and keep every other provider running,
// and a Secret created afterwards has to heal the KVM proxies on the next
// reconcile rather than needing a restart.
func lazyAuth(cfg provider.KVMConfig) func() (*sshAuth, error) {
var (
mu sync.Mutex
cached *sshAuth
)
return func() (*sshAuth, error) {
mu.Lock()
defer mu.Unlock()
if cached != nil {
return cached, nil
}
auth, err := newSSHAuth(cfg)
if err != nil {
return nil, err
}
cached = auth
return auth, nil
}
type lazySSH struct {
cfg provider.KVMConfig
mu sync.Mutex
auth *sshAuth
}
func lazyDialer(cfg provider.KVMConfig) hostDialer {
auth := lazyAuth(cfg)
return func(ctx context.Context, host provider.KVMHost) (*hostClient, error) {
a, err := auth()
if err != nil {
return nil, err
}
return a.dialer()(ctx, host)
}
// newLazySSH keeps only the SSH fields of cfg, since the loader lives as
// long as the Provider.
func newLazySSH(cfg provider.KVMConfig) *lazySSH {
return &lazySSH{cfg: provider.KVMConfig{
SSHKeyFile: cfg.SSHKeyFile,
KnownHostsFile: cfg.KnownHostsFile,
InsecureIgnoreHostKey: cfg.InsecureIgnoreHostKey,
}}
}
// dialer returns the production hostDialer: SSH to the host, forward its
// libvirt unix socket through the connection, and open a libvirt session
// over that.
func (a *sshAuth) dialer() hostDialer {
return func(ctx context.Context, host provider.KVMHost) (*hostClient, error) {
client, err := a.dialSSH(ctx, host)
if err != nil {
return nil, err
}
hc, err := connectLibvirt(ctx, client, host.Socket)
if err != nil {
client.Close()
return nil, err
}
return hc, nil
func (l *lazySSH) load() (*sshAuth, error) {
l.mu.Lock()
defer l.mu.Unlock()
if l.auth != nil {
return l.auth, nil
}
auth, err := newSSHAuth(l.cfg)
if err != nil {
return nil, err
}
l.auth = auth
return auth, nil
}
// dial is the production hostDialer.
func (l *lazySSH) dial(ctx context.Context, host provider.KVMHost) (*hostClient, error) {
a, err := l.load()
if err != nil {
return nil, err
}
return a.dial(ctx, host)
}
// dial SSHes to the host, forwards its libvirt unix socket through the
// connection, and opens a libvirt session over that.
func (a *sshAuth) dial(ctx context.Context, host provider.KVMHost) (*hostClient, error) {
client, err := a.dialSSH(ctx, host)
if err != nil {
return nil, err
}
hc, err := connectLibvirt(ctx, client, host.Socket)
if err != nil {
client.Close()
return nil, err
}
return hc, nil
}
// dialSSH establishes the SSH connection. The handshake is bounded by ctx's