feature: the package installs the Router Manager, which is no longer a package of its own.
Release / release (push) Failing after 4s
Release / release (push) Failing after 4s
This commit is contained in:
1 parent
6d90441bee
commit
8efe21bfa6
129 files changed
+17381
-104
No files matched your search
@@ -0,0 +1,63 @@
|
||||
import Refresh from '@mui/icons-material/Refresh'
|
||||
import { Alert, Box, Button, Stack } from '@mui/material'
|
||||
import { Grid, IPSEC_HEADS, Section, duration, ipsecRows, text } from './RouterPanel.tsx'
|
||||
import Toolbar from './Toolbar.tsx'
|
||||
import { DETAILS_SHAPE, request, type RouterDetails } from './api.ts'
|
||||
import { useRead } from './useRead.ts'
|
||||
|
||||
/** Reads the router's /config. */
|
||||
const readDetails = () => request<RouterDetails>('GET', '/config', DETAILS_SHAPE)
|
||||
|
||||
/**
|
||||
* How long a site-to-site connection has been up: the age of its oldest established IKE SA; "down" without one, and
|
||||
* "unknown" when the router could not list its SAs.
|
||||
*/
|
||||
function uptimeOf(sas: RouterDetails['ipsec']['sas'], name: string) {
|
||||
if (sas === null) {
|
||||
return 'unknown'
|
||||
}
|
||||
const ages = sas.filter((sa) => sa.name === name && sa.state === 'ESTABLISHED' && sa.established !== undefined).map((sa) => Number(sa.established))
|
||||
return ages.length === 0 ? 'down' : duration(Math.max(...ages))
|
||||
}
|
||||
|
||||
/**
|
||||
* The state of the router's site-to-site connections, from its /config: each with the identities and subnets the
|
||||
* router resolved for it and how long it has been up, and their IPsec security associations, child SAs, connections
|
||||
* and connection children.
|
||||
*/
|
||||
export default function SiteToSiteStatusPanel() {
|
||||
const { data: details, error, busy, refresh } = useRead(readDetails)
|
||||
|
||||
const names = new Set((details?.network.site_to_site ?? []).map((connection) => connection.name))
|
||||
const { sas, childSas, connections, children } = ipsecRows(details, (name) => names.has(name))
|
||||
|
||||
return (
|
||||
<Box component="section">
|
||||
<Toolbar description="The state of the site-to-site connections.">
|
||||
<Button variant="outlined" startIcon={<Refresh />} disabled={busy} onClick={() => void refresh()}>Refresh</Button>
|
||||
</Toolbar>
|
||||
{error && <Alert severity="error" sx={{ mb: 2, whiteSpace: 'pre-line' }}>{error}</Alert>}
|
||||
{details && (
|
||||
<Stack sx={{ gap: 2 }}>
|
||||
<Section title="Site-to-site connections">
|
||||
<Grid
|
||||
head={['Connection', 'Local identity', 'Remote identity', 'Local CIDRs', 'Remote CIDRs', 'Uptime']}
|
||||
rows={(details.network.site_to_site ?? []).map((connection) => [
|
||||
connection.name,
|
||||
text(connection.local_identity),
|
||||
text(connection.remote_identity),
|
||||
text(connection.local_cidrs),
|
||||
text(connection.remote_cidrs),
|
||||
uptimeOf(details.ipsec.sas, connection.name),
|
||||
])}
|
||||
/>
|
||||
</Section>
|
||||
<Section title="IPsec security associations"><Grid head={IPSEC_HEADS.sas} rows={sas} /></Section>
|
||||
<Section title="IPsec child SAs"><Grid head={IPSEC_HEADS.childSas} rows={childSas} /></Section>
|
||||
<Section title="IPsec connections"><Grid head={IPSEC_HEADS.connections} rows={connections} /></Section>
|
||||
<Section title="IPsec connection children"><Grid head={IPSEC_HEADS.children} rows={children} /></Section>
|
||||
</Stack>
|
||||
)}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user