mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-14 16:20:03 +00:00
Keep standalone agent machines out of the Virtualization Hosts thresholds list
A machine monitored only by the Pulse agent was listed under Alerts, Thresholds, Virtualization Hosts as well as under Machines, because the section was fed by every resource of type `agent` rather than by provider-owned virtualization nodes. The two rows do not share an override identity. The Machines row resolves through `hostOverrideIdCandidates`, which prefers the agent-derived id, while the Virtualization Hosts row reads and writes `overridesMap.get(node.id)` on the bare resource id. A custom threshold saved from the Virtualization Hosts row therefore landed under a key agent alerting never reads, so the machine kept alerting on the global default with no visible reason. The section now takes `virtualizationHostResources`, which excludes standalone Pulse-agent resources via the existing `isPulseAgentPlatformResource` classifier already used by the standalone page, platform navigation and the resource drawer. Provider-owned nodes are unaffected, since they carry provider-owner platform evidence. Those machines lose nothing: they keep their Machines row, which is the one alerting honours. Reported via support by a customer whose cloud host kept firing at the 85% global agent memory limit despite a 100% override saved on the wrong row.
This commit is contained in:
@@ -88,7 +88,7 @@ export function AlertsConfigurationSurface(props: AlertsConfigurationSurfaceProp
|
|||||||
pbsInstances={state.pbsInstances()}
|
pbsInstances={state.pbsInstances()}
|
||||||
pmgInstances={state.pmgInstances()}
|
pmgInstances={state.pmgInstances()}
|
||||||
containerRuntimes={state.containerRuntimeResources()}
|
containerRuntimes={state.containerRuntimeResources()}
|
||||||
nodes={props.byType('agent')}
|
nodes={state.virtualizationHostResources()}
|
||||||
agents={state.agentResources()}
|
agents={state.agentResources()}
|
||||||
storage={props
|
storage={props
|
||||||
.allResources()
|
.allResources()
|
||||||
|
|||||||
@@ -62,6 +62,53 @@ describe('useAlertOverridesState', () => {
|
|||||||
expect(overviewOverrides()).toEqual(result.overrides());
|
expect(overviewOverrides()).toEqual(result.overrides());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('keeps standalone agent machines out of the virtualization host list while retaining provider-owned nodes', () => {
|
||||||
|
const [hasUnsavedChanges] = createSignal(false);
|
||||||
|
const [, setOverviewOverrides] = createSignal([]);
|
||||||
|
const resources = [
|
||||||
|
// A cloud box running only the Pulse agent. It belongs to the Machines tab,
|
||||||
|
// whose overrides resolve by agent identity, so a second row here would save
|
||||||
|
// an override that agent alerting never reads.
|
||||||
|
makeResource({
|
||||||
|
id: 'docker-host-gcp-01',
|
||||||
|
name: 'docker-host-gcp-01',
|
||||||
|
type: 'agent',
|
||||||
|
platformType: 'agent',
|
||||||
|
sourceType: 'agent',
|
||||||
|
platformData: {
|
||||||
|
agent: { agentId: 'agent-gcp-01', platform: 'Linux' },
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
// A real Proxmox node must still appear under Virtualization Hosts.
|
||||||
|
makeResource({
|
||||||
|
id: 'cluster-a:pve01',
|
||||||
|
name: 'pve01',
|
||||||
|
type: 'agent',
|
||||||
|
platformType: 'proxmox-pve',
|
||||||
|
sourceType: 'api',
|
||||||
|
platformData: {
|
||||||
|
proxmox: { node: 'pve01', instance: 'cluster-a' },
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
const { result } = renderHook(() =>
|
||||||
|
useAlertOverridesState({
|
||||||
|
allResources: () => resources,
|
||||||
|
byType: (resourceType) => resources.filter((resource) => resource.type === resourceType),
|
||||||
|
children: () => [],
|
||||||
|
hasUnsavedChanges,
|
||||||
|
setOverviewOverrides,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.virtualizationHostResources().map((resource) => resource.id)).toEqual([
|
||||||
|
'cluster-a:pve01',
|
||||||
|
]);
|
||||||
|
// The standalone machine is still reachable, via the Machines tab.
|
||||||
|
expect(result.agentResources().map((resource) => resource.id)).toContain('docker-host-gcp-01');
|
||||||
|
});
|
||||||
|
|
||||||
it('projects guest overrides without agent resources and clears stale overrides when config is emptied', async () => {
|
it('projects guest overrides without agent resources and clears stale overrides when config is emptied', async () => {
|
||||||
const [hasUnsavedChanges] = createSignal(false);
|
const [hasUnsavedChanges] = createSignal(false);
|
||||||
const [overviewOverrides, setOverviewOverrides] = createSignal([]);
|
const [overviewOverrides, setOverviewOverrides] = createSignal([]);
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ import { createEffect, createMemo, createSignal, type Accessor } from 'solid-js'
|
|||||||
import type { PBSInstance, PMGInstance } from '@/types/api';
|
import type { PBSInstance, PMGInstance } from '@/types/api';
|
||||||
import type { RawOverrideConfig } from '@/types/alerts';
|
import type { RawOverrideConfig } from '@/types/alerts';
|
||||||
import type { Resource, ResourceType } from '@/types/resource';
|
import type { Resource, ResourceType } from '@/types/resource';
|
||||||
import { isAgentFacetInfrastructureResource } from '@/utils/agentResources';
|
import {
|
||||||
|
isAgentFacetInfrastructureResource,
|
||||||
|
isPulseAgentPlatformResource,
|
||||||
|
} from '@/utils/agentResources';
|
||||||
import { pbsInstanceFromResource, pmgInstanceFromResource } from '@/utils/resourceStateAdapters';
|
import { pbsInstanceFromResource, pmgInstanceFromResource } from '@/utils/resourceStateAdapters';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -48,6 +51,15 @@ export function useAlertOverridesState(props: AlertOverridesStateProps) {
|
|||||||
props.allResources().filter((resource) => isAgentFacetInfrastructureResource(resource)),
|
props.allResources().filter((resource) => isAgentFacetInfrastructureResource(resource)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Standalone Pulse-agent machines are not virtualization hosts. They own a row
|
||||||
|
// in the Machines tab, which resolves overrides by agent identity. Leaving them
|
||||||
|
// in the Virtualization Hosts list gave the same machine a second row that saved
|
||||||
|
// overrides under the bare resource id, an identity agent alerting never reads,
|
||||||
|
// so the override silently did nothing.
|
||||||
|
const virtualizationHostResources = createMemo(() =>
|
||||||
|
props.byType('agent').filter((resource) => !isPulseAgentPlatformResource(resource)),
|
||||||
|
);
|
||||||
|
|
||||||
const pbsInstances = createMemo<PBSInstance[]>(() =>
|
const pbsInstances = createMemo<PBSInstance[]>(() =>
|
||||||
props
|
props
|
||||||
.allResources()
|
.allResources()
|
||||||
@@ -157,6 +169,7 @@ export function useAlertOverridesState(props: AlertOverridesStateProps) {
|
|||||||
replaceRawOverridesConfig,
|
replaceRawOverridesConfig,
|
||||||
allGuests,
|
allGuests,
|
||||||
agentResources,
|
agentResources,
|
||||||
|
virtualizationHostResources,
|
||||||
containerRuntimeResources,
|
containerRuntimeResources,
|
||||||
pbsInstances,
|
pbsInstances,
|
||||||
pmgInstances,
|
pmgInstances,
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ export function useAlertsConfigurationState(props: AlertsConfigurationSurfacePro
|
|||||||
...configurationSnapshotState,
|
...configurationSnapshotState,
|
||||||
allGuests: overridesState.allGuests,
|
allGuests: overridesState.allGuests,
|
||||||
agentResources: overridesState.agentResources,
|
agentResources: overridesState.agentResources,
|
||||||
|
virtualizationHostResources: overridesState.virtualizationHostResources,
|
||||||
containerRuntimeResources: overridesState.containerRuntimeResources,
|
containerRuntimeResources: overridesState.containerRuntimeResources,
|
||||||
pbsInstances: overridesState.pbsInstances,
|
pbsInstances: overridesState.pbsInstances,
|
||||||
pmgInstances: overridesState.pmgInstances,
|
pmgInstances: overridesState.pmgInstances,
|
||||||
|
|||||||
Reference in New Issue
Block a user