Fix initial setup caching and container discovery defaults

This commit is contained in:
rcourtman 2025-10-22 07:34:32 +00:00
parent ff4dc49ae4
commit 4eb8bed9b5
4 changed files with 582 additions and 528 deletions

View file

@ -131,9 +131,23 @@ export const FirstRunSetup: Component = () => {
// Save credentials for display // Save credentials for display
setSavedUsername(username()); setSavedUsername(username());
setSavedPassword(useCustomPassword() ? password() : generatedPassword()); setSavedPassword(finalPassword);
setSavedToken(token); setSavedToken(token);
// Clear any cached credentials from prior sessions so a reload doesn't auto-submit again
try {
sessionStorage.removeItem('pulse_auth');
sessionStorage.removeItem('pulse_auth_user');
} catch (storageError) {
console.warn('Unable to clear cached auth session storage', storageError);
}
try {
localStorage.removeItem('apiToken');
} catch (storageError) {
console.warn('Unable to clear cached API token', storageError);
}
const bootstrapRecord: APITokenRecord = { const bootstrapRecord: APITokenRecord = {
id: 'bootstrap-token', id: 'bootstrap-token',
name: 'Bootstrap token', name: 'Bootstrap token',

View file

@ -117,6 +117,19 @@ export const QuickSecuritySetup: Component<QuickSecuritySetupProps> = (props) =>
setCredentials(newCredentials); setCredentials(newCredentials);
setShowCredentials(true); setShowCredentials(true);
try {
sessionStorage.removeItem('pulse_auth');
sessionStorage.removeItem('pulse_auth_user');
} catch (storageError) {
console.warn('Unable to clear cached auth session storage', storageError);
}
try {
localStorage.removeItem('apiToken');
} catch (storageError) {
console.warn('Unable to clear cached API token', storageError);
}
// Show success message // Show success message
showSuccess( showSuccess(
isRotation isRotation

View file

@ -84,6 +84,19 @@ func ApplyConfigToProfile(profile *envdetect.EnvironmentProfile, cfg config.Disc
} }
} }
if len(cfg.SubnetAllowlist) == 0 && shouldPruneContainerNetworks(profile.Type) {
pruned := make([]envdetect.SubnetPhase, 0, len(profile.Phases))
for _, phase := range profile.Phases {
if isLikelyContainerPhase(phase.Name) {
continue
}
pruned = append(pruned, phase)
}
if len(pruned) > 0 {
profile.Phases = pruned
}
}
// Override scan policy // Override scan policy
if cfg.MaxHostsPerScan > 0 { if cfg.MaxHostsPerScan > 0 {
profile.Policy.MaxHostsPerScan = cfg.MaxHostsPerScan profile.Policy.MaxHostsPerScan = cfg.MaxHostsPerScan
@ -102,6 +115,15 @@ func ApplyConfigToProfile(profile *envdetect.EnvironmentProfile, cfg config.Disc
} }
} }
func shouldPruneContainerNetworks(env envdetect.Environment) bool {
return env == envdetect.DockerBridge || env == envdetect.LXCUnprivileged
}
func isLikelyContainerPhase(name string) bool {
name = strings.ToLower(strings.TrimSpace(name))
return strings.Contains(name, "container")
}
func parseCIDRs(values []string, warnings *[]string) []net.IPNet { func parseCIDRs(values []string, warnings *[]string) []net.IPNet {
var subnets []net.IPNet var subnets []net.IPNet
for _, value := range values { for _, value := range values {

View file

@ -371,7 +371,6 @@ type InstanceHealth struct {
DeadLetter InstanceDLQ `json:"deadLetter"` DeadLetter InstanceDLQ `json:"deadLetter"`
} }
func schedulerKey(instanceType InstanceType, name string) string { func schedulerKey(instanceType InstanceType, name string) string {
return string(instanceType) + "::" + name return string(instanceType) + "::" + name
} }
@ -1480,8 +1479,8 @@ func New(cfg *config.Config) (*Monitor, error) {
taskQueue := NewTaskQueue() taskQueue := NewTaskQueue()
deadLetterQueue := NewTaskQueue() deadLetterQueue := NewTaskQueue()
breakers := make(map[string]*circuitBreaker) breakers := make(map[string]*circuitBreaker)
failureCounts := make(map[string]int) failureCounts := make(map[string]int)
lastOutcome := make(map[string]taskOutcome) lastOutcome := make(map[string]taskOutcome)
backoff := backoffConfig{ backoff := backoffConfig{
Initial: 5 * time.Second, Initial: 5 * time.Second,
Multiplier: 2, Multiplier: 2,
@ -1893,7 +1892,6 @@ func (m *Monitor) buildInstanceInfoCache(cfg *config.Config) {
} }
} }
func (m *Monitor) getExecutor() PollExecutor { func (m *Monitor) getExecutor() PollExecutor {
m.mu.RLock() m.mu.RLock()
exec := m.executor exec := m.executor
@ -1999,12 +1997,12 @@ func (m *Monitor) Start(ctx context.Context, wsHub *websocket.Hub) {
// Create separate tickers for polling and broadcasting // Create separate tickers for polling and broadcasting
// Hardcoded to 10 seconds since Proxmox updates cluster/resources every 10 seconds // Hardcoded to 10 seconds since Proxmox updates cluster/resources every 10 seconds
const pollingInterval = 10 * time.Second const pollingInterval = 10 * time.Second
workerCount := len(m.pveClients) + len(m.pbsClients) + len(m.pmgClients) workerCount := len(m.pveClients) + len(m.pbsClients) + len(m.pmgClients)
m.startTaskWorkers(ctx, workerCount) m.startTaskWorkers(ctx, workerCount)
pollTicker := time.NewTicker(pollingInterval) pollTicker := time.NewTicker(pollingInterval)
defer pollTicker.Stop() defer pollTicker.Stop()
broadcastTicker := time.NewTicker(pollingInterval) broadcastTicker := time.NewTicker(pollingInterval)
@ -3667,6 +3665,12 @@ func (m *Monitor) pollPVEInstance(ctx context.Context, instanceName string, clie
Bool("isCluster", modelNode.IsClusterMember). Bool("isCluster", modelNode.IsClusterMember).
Int("endpointCount", len(instanceCfg.ClusterEndpoints)). Int("endpointCount", len(instanceCfg.ClusterEndpoints)).
Msg("Temperature collection failed - check SSH access") Msg("Temperature collection failed - check SSH access")
} else if temp != nil {
log.Debug().
Str("node", node.Node).
Str("sshHost", sshHost).
Bool("available", temp.Available).
Msg("Temperature data unavailable after collection")
} }
} }
@ -3698,7 +3702,7 @@ func (m *Monitor) pollPVEInstance(ctx context.Context, instanceName string, clie
if nodeErrReason == "" { if nodeErrReason == "" {
nodeErrReason = "unknown node error" nodeErrReason = "unknown node error"
} }
nodeErr = fmt.Errorf(nodeErrReason) nodeErr = stderrors.New(nodeErrReason)
} }
m.pollMetrics.RecordNodeResult(NodePollResult{ m.pollMetrics.RecordNodeResult(NodePollResult{
@ -5233,6 +5237,7 @@ func (m *Monitor) pollPBSInstance(ctx context.Context, instanceName string, clie
Msg("PBS backup monitoring disabled") Msg("PBS backup monitoring disabled")
} }
} }
// pollPMGInstance polls a single Proxmox Mail Gateway instance // pollPMGInstance polls a single Proxmox Mail Gateway instance
func (m *Monitor) pollPMGInstance(ctx context.Context, instanceName string, client *pmg.Client) { func (m *Monitor) pollPMGInstance(ctx context.Context, instanceName string, client *pmg.Client) {
start := time.Now() start := time.Now()