mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-24 04:33:17 +00:00
Integrate reviewed truthful TrueNAS setup acceptance help
Retain both exact specialist commits and their rendered-help evidence. Existing documentation and verification only; no runtime, dependency or product-surface expansion. Full frontend suites/build remain unverified after two guest-readiness failures; rendered Chromium/WebKit and focused static evidence are proportionate to this diff. Contract-Neutral: Existing help and verification only; no runtime contract changes. Change-source: pulse-maintainer
This commit is contained in:
+19
-10
@@ -9,8 +9,13 @@ Pulse v6 includes first-class monitoring for **TrueNAS SCALE** and **TrueNAS COR
|
||||
are listed under **Platform connections**.
|
||||
3. Enter the TrueNAS URL (e.g., `https://truenas.local`), the API key, and the
|
||||
username that owns the key.
|
||||
4. Click **Test Connection** → **Save**.
|
||||
5. Data appears within one configured polling cycle (60 seconds by default).
|
||||
4. Click **Test Connection**, then **Save**. The test reads system information
|
||||
on a separate connection; it does not validate inventory or metric collection.
|
||||
5. Leave the saved connection enabled and allow at least one configured polling
|
||||
interval (60 seconds by default). Check that the appliance and expected
|
||||
inventory appear. If they do not, follow the [polling checks](#stale-truenas-data)
|
||||
without repeatedly testing or restarting; an elapsed interval is not proof
|
||||
that a poll completed.
|
||||
|
||||
## Creating a TrueNAS API Key
|
||||
|
||||
@@ -155,9 +160,11 @@ its trusted HTTPS origin without disabling certificate verification.
|
||||
### No data appearing after adding connection
|
||||
- Allow one configured polling cycle (60 seconds by default), not a fixed
|
||||
30-second wait. Check that the saved connection is enabled.
|
||||
- **Test Connection** checks authentication and the selected transport, not
|
||||
successful collection of every metric. The legacy REST diagnostic is
|
||||
expected for recognized CORE 13 systems; it is not itself a connection error.
|
||||
- **Test Connection** reads system information on a separate connection. Pools,
|
||||
datasets, disks and alerts can still fail during ordinary polling, even when
|
||||
the test succeeds. A successful test also does not establish live CPU, memory
|
||||
or History readings. The legacy REST diagnostic is expected for recognized
|
||||
CORE 13 systems; it is not itself a connection error.
|
||||
- Inspect a bounded local log excerpt for TrueNAS-related errors:
|
||||
```bash
|
||||
journalctl -u pulse -n 100 --no-pager | grep -i truenas
|
||||
@@ -236,11 +243,13 @@ collection step.
|
||||
| No timestamps advance, or no completed attempt is recorded | Check that the connection and integration are enabled, then preserve the bounded local error above. This is not proof of an invalid key. |
|
||||
| Reconnects or TrueNAS sign-ins increase while `observed.collectedAt` advances | Session turnover alone does not establish failed authentication or stopped polling. Record the timing and any existing close/error message separately from the data freshness. |
|
||||
|
||||
**Test Connection** checks connectivity and authentication, not a complete
|
||||
poll. Testing a saved connection can update `lastAttemptAt` and `lastSuccessAt`
|
||||
and reset its failure count without refreshing `observed.collectedAt`. Record
|
||||
any manual test and its time separately; a successful test is not evidence
|
||||
that missing data or stopped polling has recovered.
|
||||
**Test Connection** is not a complete poll. Some older builds, including Pulse
|
||||
6.4.1 and 6.4.5, also let a saved-connection test update `lastAttemptAt` and
|
||||
`lastSuccessAt` and reset its failure count without refreshing
|
||||
`observed.collectedAt`. Record any manual test and its time separately, and
|
||||
use the inventory observation time rather than the test time to check freshness.
|
||||
A successful test is not evidence that missing data or stopped polling has
|
||||
recovered.
|
||||
|
||||
An `app.stats` error such as **Apps are not available** concerns Apps
|
||||
collection, not necessarily the key. Check the existing Apps status in
|
||||
|
||||
@@ -22,6 +22,7 @@ const targets: Record<string, string> = {
|
||||
malformed: '/docs/API#%invalid',
|
||||
missing: '/docs/API#does-not-exist',
|
||||
troubleshooting: '/docs/TROUBLESHOOTING#recovery-mode',
|
||||
truenas: '/docs/TRUENAS',
|
||||
};
|
||||
|
||||
window.history.replaceState({}, '', targets[scenario] ?? targets.plain);
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
// The real Docs page/router/styles and shipped TrueNAS help, without a backend.
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const { chromium, webkit } = require('playwright');
|
||||
|
||||
(async () => {
|
||||
const root = '/workspace/frontend-modern';
|
||||
const artifacts = path.join(root, 'node_modules', 'truenas-connection-help-browser');
|
||||
fs.mkdirSync(artifacts, { recursive: true });
|
||||
const { createServer } = await import(path.join(root, 'node_modules/vite/dist/node/index.js'));
|
||||
const server = await createServer({
|
||||
root,
|
||||
configFile: path.join(root, 'vite.config.ts'),
|
||||
cacheDir: path.join(root, 'node_modules', '.vite-truenas-connection-help'),
|
||||
server: { host: '127.0.0.1', port: 5250, strictPort: true },
|
||||
optimizeDeps: { noDiscovery: true, include: [] },
|
||||
});
|
||||
const results = [];
|
||||
let browser;
|
||||
try {
|
||||
await server.listen();
|
||||
for (const [engine, width] of [['chromium', 1280], ['webkit', 390]]) {
|
||||
browser = await { chromium, webkit }[engine].launch(engine === 'chromium'
|
||||
? { headless: true, channel: 'chromium', args: ['--no-sandbox'] }
|
||||
: { headless: true });
|
||||
const page = await browser.newPage({ viewport: { width, height: 900 },
|
||||
...(engine === 'webkit' ? { isMobile: true, hasTouch: true } : {}) });
|
||||
const errors = [];
|
||||
page.on('pageerror', (error) => errors.push(error.message));
|
||||
page.on('console', (message) => {
|
||||
if (message.type() === 'error') errors.push(message.text());
|
||||
});
|
||||
await page.goto('http://127.0.0.1:5250/browser-tests/docs-fragment-navigation.html?scenario=truenas',
|
||||
{ waitUntil: 'domcontentloaded', timeout: 60_000 });
|
||||
const quickStart = page.getByRole('heading', { name: 'Quick Start', exact: true });
|
||||
await quickStart.waitFor();
|
||||
if (engine === 'webkit') {
|
||||
await page.evaluate(async () => {
|
||||
document.documentElement.classList.add('dark');
|
||||
await new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve)));
|
||||
await Promise.all(document.getAnimations().map((animation) => animation.finished.catch(() => {})));
|
||||
});
|
||||
}
|
||||
const article = await page.locator('article').innerText();
|
||||
for (const text of ['it does not validate inventory or metric collection',
|
||||
'an elapsed interval is not proof that a poll completed',
|
||||
'Some older builds, including Pulse 6.4.1 and 6.4.5',
|
||||
'use the inventory observation time rather than the test time',
|
||||
'do not copy a token or cookie', 'Do not post the full connection response'])
|
||||
assert.ok(article.includes(text), text);
|
||||
assert.ok(!article.includes('Data appears within one configured polling cycle'));
|
||||
await quickStart.evaluate((heading) => heading.scrollIntoView({ block: 'start' }));
|
||||
await page.screenshot({ path: path.join(artifacts, `${engine}-setup.png`) });
|
||||
const checks = page.getByRole('link', { name: 'polling checks', exact: true }).first();
|
||||
await checks.focus();
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitForFunction(() => {
|
||||
const heading = document.getElementById('stale-truenas-data');
|
||||
return heading && heading.getBoundingClientRect().top >= 0
|
||||
&& heading.getBoundingClientRect().top < innerHeight;
|
||||
});
|
||||
assert.ok(page.url().endsWith('/docs/TRUENAS#stale-truenas-data'));
|
||||
assert.ok(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth + 1));
|
||||
await page.screenshot({ path: path.join(artifacts, `${engine}-polling.png`) });
|
||||
assert.deepEqual(errors, []);
|
||||
results.push({ engine, version: browser.version(), width,
|
||||
probeScope: true, noGuaranteedPoll: true, versionQualifiedWarning: true,
|
||||
keyboardPollingLink: true, noDocumentOverflow: true, errors });
|
||||
await browser.close();
|
||||
browser = undefined;
|
||||
}
|
||||
const result = { result: 'passed', playwright: require('playwright/package.json').version,
|
||||
scope: 'shipped help rendering/navigation, not native TrueNAS polling', results };
|
||||
fs.writeFileSync(path.join(artifacts, 'result.json'), JSON.stringify(result, null, 2) + '\n');
|
||||
console.log(JSON.stringify(result));
|
||||
} finally {
|
||||
if (browser) await browser.close();
|
||||
await server.close();
|
||||
}
|
||||
})().catch((error) => { console.error(error); process.exitCode = 1; });
|
||||
@@ -9,8 +9,13 @@ Pulse v6 includes first-class monitoring for **TrueNAS SCALE** and **TrueNAS COR
|
||||
are listed under **Platform connections**.
|
||||
3. Enter the TrueNAS URL (e.g., `https://truenas.local`), the API key, and the
|
||||
username that owns the key.
|
||||
4. Click **Test Connection** → **Save**.
|
||||
5. Data appears within one configured polling cycle (60 seconds by default).
|
||||
4. Click **Test Connection**, then **Save**. The test reads system information
|
||||
on a separate connection; it does not validate inventory or metric collection.
|
||||
5. Leave the saved connection enabled and allow at least one configured polling
|
||||
interval (60 seconds by default). Check that the appliance and expected
|
||||
inventory appear. If they do not, follow the [polling checks](#stale-truenas-data)
|
||||
without repeatedly testing or restarting; an elapsed interval is not proof
|
||||
that a poll completed.
|
||||
|
||||
## Creating a TrueNAS API Key
|
||||
|
||||
@@ -155,9 +160,11 @@ its trusted HTTPS origin without disabling certificate verification.
|
||||
### No data appearing after adding connection
|
||||
- Allow one configured polling cycle (60 seconds by default), not a fixed
|
||||
30-second wait. Check that the saved connection is enabled.
|
||||
- **Test Connection** checks authentication and the selected transport, not
|
||||
successful collection of every metric. The legacy REST diagnostic is
|
||||
expected for recognized CORE 13 systems; it is not itself a connection error.
|
||||
- **Test Connection** reads system information on a separate connection. Pools,
|
||||
datasets, disks and alerts can still fail during ordinary polling, even when
|
||||
the test succeeds. A successful test also does not establish live CPU, memory
|
||||
or History readings. The legacy REST diagnostic is expected for recognized
|
||||
CORE 13 systems; it is not itself a connection error.
|
||||
- Inspect a bounded local log excerpt for TrueNAS-related errors:
|
||||
```bash
|
||||
journalctl -u pulse -n 100 --no-pager | grep -i truenas
|
||||
@@ -236,11 +243,13 @@ collection step.
|
||||
| No timestamps advance, or no completed attempt is recorded | Check that the connection and integration are enabled, then preserve the bounded local error above. This is not proof of an invalid key. |
|
||||
| Reconnects or TrueNAS sign-ins increase while `observed.collectedAt` advances | Session turnover alone does not establish failed authentication or stopped polling. Record the timing and any existing close/error message separately from the data freshness. |
|
||||
|
||||
**Test Connection** checks connectivity and authentication, not a complete
|
||||
poll. Testing a saved connection can update `lastAttemptAt` and `lastSuccessAt`
|
||||
and reset its failure count without refreshing `observed.collectedAt`. Record
|
||||
any manual test and its time separately; a successful test is not evidence
|
||||
that missing data or stopped polling has recovered.
|
||||
**Test Connection** is not a complete poll. Some older builds, including Pulse
|
||||
6.4.1 and 6.4.5, also let a saved-connection test update `lastAttemptAt` and
|
||||
`lastSuccessAt` and reset its failure count without refreshing
|
||||
`observed.collectedAt`. Record any manual test and its time separately, and
|
||||
use the inventory observation time rather than the test time to check freshness.
|
||||
A successful test is not evidence that missing data or stopped polling has
|
||||
recovered.
|
||||
|
||||
An `app.stats` error such as **Apps are not available** concerns Apps
|
||||
collection, not necessarily the key. Check the existing Apps status in
|
||||
|
||||
@@ -61,6 +61,24 @@ function getRuntimeSourceFiles(dir: string): string[] {
|
||||
}
|
||||
|
||||
describe('docsLinks', () => {
|
||||
it('keeps TrueNAS setup acceptance separate from a system-information probe', () => {
|
||||
const truenas = readFileSync(path.join(repoRoot, 'docs', 'TRUENAS.md'), 'utf8');
|
||||
const setup = truenas.split('## Quick Start')[1].split('## Creating a TrueNAS API Key')[0];
|
||||
expect(setup).toContain('it does not validate inventory or metric collection');
|
||||
expect(setup).toContain('an elapsed interval is not proof');
|
||||
expect(setup).toContain('[polling checks](#stale-truenas-data)');
|
||||
expect(setup).not.toContain('Data appears within one configured polling cycle');
|
||||
const noData = truenas
|
||||
.split('### No data appearing after adding connection')[1]
|
||||
.split('### Inventory works')[0];
|
||||
expect(noData).toContain('Pools,\n datasets, disks and alerts can still fail');
|
||||
expect(noData).toContain('does not establish live CPU, memory');
|
||||
expect(truenas).toContain('Some older builds, including Pulse\n6.4.1 and 6.4.5');
|
||||
expect(truenas).toContain('use the inventory observation time rather than the test time');
|
||||
expect(truenas).toContain('do not copy a token or cookie');
|
||||
expect(truenas).toContain('Do not post the full connection response');
|
||||
});
|
||||
|
||||
it('keeps restored Proxmox node network details in the candidate packet', () => {
|
||||
const releaseNotes = readFileSync(
|
||||
path.join(repoRoot, 'docs', 'releases', 'RELEASE_NOTES_v6.4.0-rc.1.md'),
|
||||
|
||||
Reference in New Issue
Block a user