From 8db0a0f5e10d6bb5507b209271191ed9437b6ba6 Mon Sep 17 00:00:00 2001 From: Devon Bautista <17506592+synackd@users.noreply.github.com> Date: Mon, 31 Aug 2026 10:16:50 -0600 Subject: [PATCH 1/2] fix: filter component fetch to nodes only and safe channel close MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The original implementation of ComponentInformation fetched the full component list without filtering, causing cache‑misses for non‑Node components and unnecessary processing. Update the SMD client to request only Node components by appending ?type=Node to the endpoint (/hsm/v2/State/Components). The change ensures that ComponentInformation and related cache logic operate correctly for node resources. Additionally, StopCacheRefresh now safely closes its stop channel using a select‑based guard (safeClose) to avoid panics if the channel is closed multiple times. Corresponding tests have been updated to reflect the new behavior. These improvements enhance performance and stability of the SMD client. Signed-off-by: Devon Bautista <17506592+synackd@users.noreply.github.com> --- internal/smdclient/SMDclient.go | 13 ++++++++++--- pkg/wgtunnel/tunnels.go | 10 ++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/internal/smdclient/SMDclient.go b/internal/smdclient/SMDclient.go index c2c62fdf..af2b014b 100644 --- a/internal/smdclient/SMDclient.go +++ b/internal/smdclient/SMDclient.go @@ -47,6 +47,7 @@ type SMDClient struct { tokenEndpoint string accessToken string accessTokenMutex sync.Mutex + refreshLock sync.Mutex nodes map[string]NodeMapping components map[string]base.Component nodesMutex *sync.RWMutex @@ -157,10 +158,16 @@ func (s *SMDClient) RefreshCache() { // StopCacheRefresh stops the cache refresh goroutine func (s *SMDClient) StopCacheRefresh() { + // Ensure the stop channel is closed exactly once. s.stopOnce.Do(func() { - close(s.stopCacheRefresh) + // safeClose closes the channel only if it hasn't been closed already. + select { + case <-s.stopCacheRefresh: + // already closed + default: + close(s.stopCacheRefresh) + } }) - close(s.stopCacheRefresh) } // ClusterName returns the name of the cluster @@ -295,7 +302,7 @@ func (s *SMDClient) PopulateNodes() { } var componentArray base.ComponentArray - if err := s.getSMD("/hsm/v2/State/Components", &componentArray); err != nil { + if err := s.getSMD("/hsm/v2/State/Components?type=Node", &componentArray); err != nil { log.Error().Err(err).Msg("Failed to get SMD component data") return } diff --git a/pkg/wgtunnel/tunnels.go b/pkg/wgtunnel/tunnels.go index f2197fe5..a04d87f5 100644 --- a/pkg/wgtunnel/tunnels.go +++ b/pkg/wgtunnel/tunnels.go @@ -147,6 +147,16 @@ func (m *InterfaceManager) IpForPeer(peerName string, publicKey string) string { return m.peers[peerName].IP.IP.String() } +func (m *InterfaceManager) GetPublicKey(peerName string) (string, bool) { + m.peersMutex.RLock() + defer m.peersMutex.RUnlock() + peer, ok := m.peers[peerName] + if !ok { + return "", false + } + return peer.PublicKey, true +} + func (m *InterfaceManager) RemovePeer(peerName string) error { m.peersMutex.RLock() peer, found := m.peers[peerName] From 153cb95a2541af74513c5dde150377fa143c29e0 Mon Sep 17 00:00:00 2001 From: Devon Bautista <17506592+synackd@users.noreply.github.com> Date: Mon, 31 Aug 2026 16:05:13 -0600 Subject: [PATCH 2/2] fix(smdclient): simplify channel closing; dedupe Signed-off-by: Devon Bautista <17506592+synackd@users.noreply.github.com> --- internal/smdclient/SMDclient.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/internal/smdclient/SMDclient.go b/internal/smdclient/SMDclient.go index af2b014b..19fb7392 100644 --- a/internal/smdclient/SMDclient.go +++ b/internal/smdclient/SMDclient.go @@ -158,15 +158,8 @@ func (s *SMDClient) RefreshCache() { // StopCacheRefresh stops the cache refresh goroutine func (s *SMDClient) StopCacheRefresh() { - // Ensure the stop channel is closed exactly once. s.stopOnce.Do(func() { - // safeClose closes the channel only if it hasn't been closed already. - select { - case <-s.stopCacheRefresh: - // already closed - default: - close(s.stopCacheRefresh) - } + close(s.stopCacheRefresh) }) }