mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-24 12:13:28 +00:00
refactor(settings): keep truenas onboarding api-first
This commit is contained in:
@@ -195,6 +195,17 @@ management, and fleet control surfaces.
|
||||
where the first-host scoped install token is prepared from setup handoff,
|
||||
not as a second manual token-generation task the operator still needs to
|
||||
figure out.
|
||||
10. Keep API-backed platform onboarding explicit across
|
||||
`frontend-modern/src/components/Settings/infrastructureOperationsModel.tsx`,
|
||||
`frontend-modern/src/components/Settings/InfrastructureInstallerSection.tsx`,
|
||||
`frontend-modern/src/components/Settings/useInfrastructureInstallState.tsx`,
|
||||
`frontend-modern/src/components/Settings/InfrastructureWorkspace.tsx`, and
|
||||
`frontend-modern/src/components/SetupWizard/SetupCompletionPanel.tsx`.
|
||||
TrueNAS must be presented as a Platform connections workflow first, not as
|
||||
a dedicated Unified Agent install profile. The install workspace may remain
|
||||
available for optional later agent augmentation on TrueNAS, but first-run
|
||||
copy, alternative CTAs, and install-profile lists must not imply that an
|
||||
agent install is the required bootstrap for TrueNAS support in Pulse.
|
||||
|
||||
## Current State
|
||||
|
||||
|
||||
@@ -228,17 +228,6 @@ Own canonical runtime payload shapes between backend and frontend.
|
||||
operators can receive the first success handoff without typing a hostname
|
||||
or agent ID.
|
||||
20. Keep the shared first-run install-token transport explicit on
|
||||
21. Keep connected-infrastructure surface vocabulary canonical across the
|
||||
shared `/api/state` and reporting/install consumers: `frontend-modern/src/types/api.ts`
|
||||
must treat `truenas` as a first-class connected-infrastructure surface kind,
|
||||
and connected-infrastructure consumers such as
|
||||
`frontend-modern/src/components/Settings/infrastructureOperationsModel.tsx`
|
||||
and
|
||||
`frontend-modern/src/components/Settings/useInfrastructureReportingState.tsx`
|
||||
must preserve the transport distinction between machine-managed surfaces
|
||||
(`agent`, `docker`, `kubernetes`) and platform-connections-managed
|
||||
surfaces (`proxmox`, `pbs`, `pmg`, `truenas`) instead of collapsing them
|
||||
into one uninstall/stop-monitoring model.
|
||||
`/api/security/tokens` as used by
|
||||
`frontend-modern/src/components/Settings/useInfrastructureInstallState.tsx`:
|
||||
once quick setup has produced the setup handoff credentials, the canonical
|
||||
@@ -249,7 +238,33 @@ Own canonical runtime payload shapes between backend and frontend.
|
||||
install-state surface must describe that prepared token path consistently
|
||||
with the live runtime behavior rather than directing the operator to create
|
||||
another install token manually.
|
||||
21. Keep local trial-start transport explicit on the shared commercial API
|
||||
21. Keep connected-infrastructure surface vocabulary canonical across the
|
||||
shared `/api/state` and reporting/install consumers:
|
||||
`frontend-modern/src/types/api.ts` must treat `truenas` as a first-class
|
||||
connected-infrastructure surface kind, and connected-infrastructure
|
||||
consumers such as
|
||||
`frontend-modern/src/components/Settings/infrastructureOperationsModel.tsx`
|
||||
and
|
||||
`frontend-modern/src/components/Settings/useInfrastructureReportingState.tsx`
|
||||
must preserve the transport distinction between machine-managed surfaces
|
||||
(`agent`, `docker`, `kubernetes`) and platform-connections-managed
|
||||
surfaces (`proxmox`, `pbs`, `pmg`, `truenas`) instead of collapsing them
|
||||
into one uninstall/stop-monitoring model.
|
||||
22. Keep API-backed first-target onboarding canonical on that same shared
|
||||
infrastructure-settings boundary:
|
||||
`frontend-modern/src/components/Settings/infrastructureOperationsModel.tsx`,
|
||||
`frontend-modern/src/components/Settings/useInfrastructureInstallState.tsx`,
|
||||
`frontend-modern/src/components/Settings/InfrastructureInstallerSection.tsx`,
|
||||
`frontend-modern/src/components/Settings/InfrastructureWorkspace.tsx`, and
|
||||
`frontend-modern/src/components/SetupWizard/SetupCompletionPanel.tsx` must
|
||||
present TrueNAS and other API-backed platforms as Platform connections-first
|
||||
onboarding rather than as dedicated unified-agent install profiles. The
|
||||
shared host-install contract may guide operators through the first
|
||||
agent-managed host, but alternate CTAs and setup-completion guidance must
|
||||
route API-backed first systems to `/settings/infrastructure/platforms`
|
||||
instead of implying that a host install command is required before those
|
||||
platforms can report into Pulse.
|
||||
23. Keep local trial-start transport explicit on the shared commercial API
|
||||
boundary: `/api/license/trial/start` must preserve the hosted-signup
|
||||
redirect contract during the allowed retry burst, then return the actual
|
||||
remaining backoff in both `Retry-After` and
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { Component } from 'solid-js';
|
||||
import { For, Show, createSignal } from 'solid-js';
|
||||
import Server from 'lucide-solid/icons/server';
|
||||
import { ProxmoxIcon } from '@/components/icons/ProxmoxIcon';
|
||||
import SettingsPanel from '@/components/shared/SettingsPanel';
|
||||
import { copyToClipboard } from '@/utils/clipboard';
|
||||
import { formatAbsoluteTime, formatRelativeTime } from '@/utils/format';
|
||||
@@ -138,31 +137,29 @@ export const InfrastructureInstallerSection: Component = () => {
|
||||
</Show>
|
||||
|
||||
<div class="rounded-md border border-blue-200 bg-blue-50 px-4 py-3 text-sm text-blue-900 dark:border-blue-700 dark:bg-blue-900 dark:text-blue-100">
|
||||
<p class="font-semibold">Start with the first host you want Pulse to monitor.</p>
|
||||
<p class="font-semibold">Use this workspace for the first agent-managed host.</p>
|
||||
<p class="mt-1 text-xs text-blue-800 dark:text-blue-200">
|
||||
Install the Pulse agent on that system first. Once it connects, Pulse can keep using this
|
||||
workspace to add more hosts and layered platform integrations.
|
||||
Install the Pulse agent here only when the first system should run the unified agent
|
||||
directly. If the first system is API-backed, such as TrueNAS or Proxmox, open Platform
|
||||
connections instead.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Show when={!state.isEmbedded()}>
|
||||
<div class="rounded-md border border-emerald-200 bg-emerald-50 px-4 py-3 text-sm text-emerald-900 dark:border-emerald-700 dark:bg-emerald-900 dark:text-emerald-100">
|
||||
<div class="flex items-start gap-3">
|
||||
<ProxmoxIcon class="mt-0.5 h-5 w-5 shrink-0 text-amber-500" />
|
||||
<div class="flex-1">
|
||||
<p class="text-sm">
|
||||
Proxmox nodes can be added here with the unified agent for extra capabilities like
|
||||
temperature monitoring and Pulse Patrol automation (auto-creates the required token
|
||||
and links the node).
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
onClick={state.openDirectProxmoxSetup}
|
||||
class="mt-2 inline-flex min-h-10 sm:min-h-9 items-center rounded-md px-2 py-1.5 text-sm font-medium text-emerald-800 underline hover:bg-emerald-100 hover:text-emerald-900 dark:text-emerald-200 dark:hover:bg-emerald-900 dark:hover:text-emerald-100"
|
||||
>
|
||||
Need direct setup instead? Open Proxmox →
|
||||
</button>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<p class="text-sm">
|
||||
API-backed platforms such as Proxmox and TrueNAS belong in Platform connections. Use
|
||||
this install workspace only for systems where Pulse should run the unified agent on
|
||||
the machine itself.
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
onClick={state.openPlatformConnections}
|
||||
class="inline-flex min-h-10 sm:min-h-9 items-center rounded-md px-2 py-1.5 text-sm font-medium text-emerald-800 underline hover:bg-emerald-100 hover:text-emerald-900 dark:text-emerald-200 dark:hover:bg-emerald-900 dark:hover:text-emerald-100"
|
||||
>
|
||||
Open Platform connections →
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
@@ -463,6 +460,10 @@ export const InfrastructureInstallerSection: Component = () => {
|
||||
<p class="mt-1.5 text-xs text-muted">
|
||||
{state.getSelectedInstallProfile().description}
|
||||
</p>
|
||||
<p class="mt-1.5 text-xs text-muted">
|
||||
API-backed platforms such as TrueNAS connect through Platform connections
|
||||
rather than a dedicated install profile here.
|
||||
</p>
|
||||
<Show when={state.getInstallProfileFlags().length > 0}>
|
||||
<p class="mt-1.5 text-xs text-muted">
|
||||
Adds flags to shell-based install commands:{' '}
|
||||
|
||||
@@ -33,17 +33,17 @@ export const InfrastructureWorkspace: Component<InfrastructureWorkspaceProps> =
|
||||
<div class="space-y-2">
|
||||
<h3 class="text-base font-semibold text-base-content">Connect your first system</h3>
|
||||
<p class="text-sm text-muted">
|
||||
Start with Install on a host to connect the first machine you want Pulse to monitor.
|
||||
If you already know you want an API-backed platform such as Proxmox or TrueNAS
|
||||
instead, go straight to Platform connections.
|
||||
Use Install on a host for the first machine that should run the unified agent. If the
|
||||
first system is API-backed, such as Proxmox or TrueNAS, go straight to Platform
|
||||
connections.
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid gap-3 lg:grid-cols-3">
|
||||
<div class="rounded-md border border-border bg-surface px-4 py-3">
|
||||
<p class="text-xs font-semibold uppercase tracking-wide text-muted">1. Choose path</p>
|
||||
<p class="mt-1 text-sm text-base-content">
|
||||
Install Pulse on a host first, or open Platform connections for Proxmox, TrueNAS,
|
||||
and other systems Pulse should poll through their own APIs.
|
||||
Choose Install on a host for agent-managed systems, or open Platform connections
|
||||
for Proxmox, TrueNAS, and other systems Pulse should poll through their own APIs.
|
||||
</p>
|
||||
</div>
|
||||
<div class="rounded-md border border-border bg-surface px-4 py-3">
|
||||
|
||||
+30
-2
@@ -120,9 +120,9 @@ describe('InfrastructureOperationsController ownership guardrails', () => {
|
||||
expect(infrastructureOperationsStateSource).not.toContain('renderStopMonitoringDialog');
|
||||
expect(infrastructureInstallStateSource).toContain('export const useInfrastructureInstallState');
|
||||
expect(infrastructureInstallStateSource).toContain('MonitoringAPI.getState()');
|
||||
expect(infrastructureInstallStateSource).toContain('./platformConnectionsModel');
|
||||
expect(infrastructureInstallStateSource).toContain('./infrastructureWorkspaceModel');
|
||||
expect(infrastructureInstallStateSource).toContain(
|
||||
"navigate(buildPlatformConnectionsPath('proxmox'))",
|
||||
"navigate(buildInfrastructureWorkspacePath('platforms'))",
|
||||
);
|
||||
expect(infrastructureInstallStateSource).not.toContain(
|
||||
"navigate('/settings/infrastructure/proxmox')",
|
||||
@@ -2722,6 +2722,34 @@ describe('InfrastructureOperationsController platform commands', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('keeps TrueNAS out of host install profiles and routes the alternative CTA to platform connections', async () => {
|
||||
createTokenMock.mockResolvedValue({
|
||||
token: 'test-token',
|
||||
record: {
|
||||
id: 'token-record',
|
||||
name: 'Test Token',
|
||||
prefix: 'abc',
|
||||
suffix: '123',
|
||||
createdAt: new Date().toISOString(),
|
||||
},
|
||||
});
|
||||
|
||||
setupComponent();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: /Generate token/i }));
|
||||
|
||||
await waitFor(() => expect(createTokenMock).toHaveBeenCalled(), { interval: 0 });
|
||||
await waitFor(() => {
|
||||
expect(getTargetProfileSelect()).toBeInTheDocument();
|
||||
});
|
||||
|
||||
expect(screen.queryByRole('option', { name: 'TrueNAS SCALE agent' })).toBeNull();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: /Open Platform connections/i }));
|
||||
|
||||
expect(navigateMock).toHaveBeenCalledWith('/settings/infrastructure/platforms');
|
||||
});
|
||||
|
||||
it('tracks install command copies', async () => {
|
||||
createTokenMock.mockResolvedValue({
|
||||
token: 'test-token',
|
||||
|
||||
+5
@@ -1,6 +1,7 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import type { ConnectedInfrastructureItem } from '@/types/api';
|
||||
import {
|
||||
INSTALL_PROFILE_OPTIONS,
|
||||
getPlatformConnectionsPathForCapability,
|
||||
hasMachineInstallActions,
|
||||
getPowerShellInstallProfileEnvFromFlags,
|
||||
@@ -146,4 +147,8 @@ describe('infrastructure operations model', () => {
|
||||
'$env:PULSE_PROXMOX_TYPE="pbs"',
|
||||
]);
|
||||
});
|
||||
|
||||
it('keeps api-backed TrueNAS out of the host install profile list', () => {
|
||||
expect(INSTALL_PROFILE_OPTIONS.map((option) => option.value)).not.toContain('truenas');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -59,7 +59,7 @@ describe('InfrastructureWorkspace', () => {
|
||||
expect(screen.getByText('Connect your first system')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(
|
||||
'Start with Install on a host to connect the first machine you want Pulse to monitor. If you already know you want an API-backed platform such as Proxmox or TrueNAS instead, go straight to Platform connections.',
|
||||
'Use Install on a host for the first machine that should run the unified agent. If the first system is API-backed, such as Proxmox or TrueNAS, go straight to Platform connections.',
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByText('1. Choose path')).toBeInTheDocument();
|
||||
|
||||
@@ -23,8 +23,7 @@ export type InstallProfile =
|
||||
| 'docker'
|
||||
| 'kubernetes'
|
||||
| 'proxmox-pve'
|
||||
| 'proxmox-pbs'
|
||||
| 'truenas';
|
||||
| 'proxmox-pbs';
|
||||
|
||||
export type SetupHandoffState = {
|
||||
username: string;
|
||||
@@ -337,13 +336,6 @@ export const INSTALL_PROFILE_OPTIONS: InstallProfileOption[] = [
|
||||
description: 'Force Proxmox integration and register as a PBS node.',
|
||||
flags: ['--enable-proxmox', '--proxmox-type pbs'],
|
||||
},
|
||||
{
|
||||
value: 'truenas',
|
||||
label: 'TrueNAS SCALE agent',
|
||||
description:
|
||||
'Use default auto-detection; installer applies TrueNAS-safe service handling automatically.',
|
||||
flags: [],
|
||||
},
|
||||
];
|
||||
|
||||
export const buildCommandsByPlatform = (
|
||||
|
||||
@@ -17,7 +17,6 @@ import { getPulseBaseUrl } from '@/utils/url';
|
||||
import { logger } from '@/utils/logger';
|
||||
import { STORAGE_KEYS } from '@/utils/localStorage';
|
||||
import { buildInfrastructureWorkspacePath } from './infrastructureWorkspaceModel';
|
||||
import { buildPlatformConnectionsPath } from './platformConnectionsModel';
|
||||
import {
|
||||
buildUnixAgentInstallCommand,
|
||||
buildWindowsAgentInstallCommand,
|
||||
@@ -471,8 +470,8 @@ Pulse prepares the first-host install token from setup so you can move straight
|
||||
}));
|
||||
});
|
||||
|
||||
const openDirectProxmoxSetup = () => {
|
||||
navigate(buildPlatformConnectionsPath('proxmox'));
|
||||
const openPlatformConnections = () => {
|
||||
navigate(buildInfrastructureWorkspacePath('platforms'));
|
||||
};
|
||||
|
||||
const openDashboard = () => {
|
||||
@@ -518,7 +517,7 @@ Pulse prepares the first-host install token from setup so you can move straight
|
||||
lookupValue,
|
||||
lookupWasAutoDetected,
|
||||
openDashboard,
|
||||
openDirectProxmoxSetup,
|
||||
openPlatformConnections,
|
||||
openInfrastructureInventory,
|
||||
requiresToken,
|
||||
selectedAgentUrl,
|
||||
|
||||
@@ -50,28 +50,28 @@ interface CompleteStepProps {
|
||||
const UNIFIED_RESOURCE_GUIDANCE = {
|
||||
title: 'What happens next',
|
||||
description:
|
||||
'Pulse is now secured. Your next step is to install the Pulse agent on the first system you want to monitor, then let Pulse discover and enrich that system over time.',
|
||||
'Pulse is now secured. Next, choose the first infrastructure path: use Infrastructure Install for a host that should run the unified agent, or use Platform connections for API-backed platforms like Proxmox and TrueNAS.',
|
||||
steps: [
|
||||
{
|
||||
title: 'Open Infrastructure Install',
|
||||
description:
|
||||
'Use the canonical install workspace where Pulse prepares the first-host install token from setup and keeps the connection settings together.',
|
||||
'Use the canonical install workspace where Pulse prepares the first-host install token from setup and keeps Platform connections beside it when the first target is API-backed.',
|
||||
},
|
||||
{
|
||||
title: 'Copy the command for your target system',
|
||||
description:
|
||||
'Choose Linux, macOS, Windows, or another supported target and copy the matching command.',
|
||||
'Choose Linux, macOS, Windows, or another supported target only when the first system should run the unified agent directly.',
|
||||
},
|
||||
{
|
||||
title: 'Run it on the first host you want to monitor',
|
||||
description:
|
||||
'When the agent connects, Pulse creates your first monitored system and you can add more infrastructure from there.',
|
||||
'When that agent-managed host connects, Pulse creates your first monitored system and you can add more infrastructure from there.',
|
||||
},
|
||||
],
|
||||
inventoryFacts: [
|
||||
'Start with one host, then add more systems later from the same install workspace.',
|
||||
'Infrastructure Install owns the token, connection URL, TLS/CA settings, and platform-specific commands.',
|
||||
'Platform connections remains available for API-backed platforms like Proxmox and TrueNAS when you need it.',
|
||||
'API-backed platforms like Proxmox and TrueNAS use Platform connections instead of a dedicated install profile in Infrastructure Install.',
|
||||
],
|
||||
} as const;
|
||||
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ describe('SetupCompletionPanel guardrails', () => {
|
||||
expect(setupCompletionPanelSource).toContain('First host first');
|
||||
expect(setupCompletionPanelSource).toContain('Start with one host, then add more systems later from the same install workspace.');
|
||||
expect(setupCompletionPanelSource).toContain(
|
||||
'Platform connections remains available for API-backed platforms like Proxmox and TrueNAS when you need it.',
|
||||
'API-backed platforms like Proxmox and TrueNAS use Platform connections instead of a dedicated install profile in Infrastructure Install.',
|
||||
);
|
||||
expect(setupCompletionPanelSource).not.toContain('Smart Auto-Detection');
|
||||
expect(setupCompletionPanelSource).not.toContain('Agent Metrics');
|
||||
|
||||
@@ -123,7 +123,12 @@ describe('SetupCompletionPanel', () => {
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(
|
||||
'Use the canonical install workspace where Pulse prepares the first-host install token from setup and keeps the connection settings together.',
|
||||
'Use the canonical install workspace where Pulse prepares the first-host install token from setup and keeps Platform connections beside it when the first target is API-backed.',
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(
|
||||
'API-backed platforms like Proxmox and TrueNAS use Platform connections instead of a dedicated install profile in Infrastructure Install.',
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user