Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SSH info to Instance Connect tab #2339

Merged
merged 11 commits into from
Aug 22, 2024
103 changes: 86 additions & 17 deletions app/pages/project/instances/instance/tabs/ConnectTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,102 @@
* Copyright Oxide Computer Company
*/

import { Link } from 'react-router-dom'
import type { ReactNode } from 'react'
import { Link, type LoaderFunctionArgs } from 'react-router-dom'

import { apiQueryClient, useApiQuery } from '~/api'
import { EquivalentCliCommand } from '~/components/EquivalentCliCommand'
import { useInstanceSelector } from '~/hooks'
import { getInstanceSelector, useInstanceSelector, useProjectSelector } from '~/hooks'
import { buttonStyle } from '~/ui/lib/Button'
import { SettingsGroup } from '~/ui/lib/SettingsGroup'
import { cliCmd } from '~/util/cli-cmd'
import { pb } from '~/util/path-builder'

ConnectTab.loader = async ({ params }: LoaderFunctionArgs) => {
const { project, instance } = getInstanceSelector(params)
await apiQueryClient.prefetchQuery('instanceExternalIpList', {
path: { instance },
query: { project },
})
return null
}

const InlineCode = ({ children }: { children: ReactNode }) => (
<code className="h-4 whitespace-nowrap rounded-sm px-[3px] py-[1px] !lowercase text-mono-sm text-secondary bg-secondary">
{children}
</code>
)

export function ConnectTab() {
const { project, instance } = useInstanceSelector()
const { data: externalIps } = useApiQuery('instanceExternalIpList', {
path: { instance },
query: { project },
})
const newFloatingIpLink = pb.floatingIpsNew(useProjectSelector())
const floatingIps = externalIps?.items?.filter((ip) => ip.kind === 'floating')
// default to a floating IP; fall back to ephemeral IP, if it exists
const externalIp = (floatingIps?.[0] || externalIps?.items?.[0])?.ip
const sshCopy = externalIp ? (
<>
<p>
If you specified SSH keys when you created this instance, you can connect to it
through an external IP: <InlineCode>ssh [username]@{externalIp}</InlineCode>
</p>
<p>
The <InlineCode>[username]</InlineCode> in the SSH command will depend on your
instance’s boot disk’s OS, but might be <InlineCode>debian</InlineCode>,{' '}
<InlineCode>ubuntu</InlineCode>, <InlineCode>arch</InlineCode>, etc.
charliepark marked this conversation as resolved.
Show resolved Hide resolved
</p>
</>
) : (
<p>
If you specified SSH keys when you created this instance, you can create an external
IP via the{' '}
<Link to={newFloatingIpLink} className="link-with-underline">
Floating IPs page
</Link>{' '}
to connect to your instance via SSH.
</p>
)

return (
<SettingsGroup.Container>
<SettingsGroup.Body>
<SettingsGroup.Title>Serial console</SettingsGroup.Title>
Connect to your instance&rsquo;s serial console
</SettingsGroup.Body>
<SettingsGroup.Footer>
<EquivalentCliCommand command={cliCmd.serialConsole({ project, instance })} />
<Link
to={pb.serialConsole({ project, instance })}
className={buttonStyle({ size: 'sm' })}
>
Connect
</Link>
</SettingsGroup.Footer>
</SettingsGroup.Container>
<div className="space-y-6">
<SettingsGroup.Container>
<SettingsGroup.Body>
<SettingsGroup.Title>Serial console</SettingsGroup.Title>
Connect to your instance&rsquo;s serial console
</SettingsGroup.Body>
<SettingsGroup.Footer>
<EquivalentCliCommand command={cliCmd.serialConsole({ project, instance })} />
<Link
to={pb.serialConsole({ project, instance })}
className={buttonStyle({ size: 'sm' })}
>
Connect
</Link>
</SettingsGroup.Footer>
</SettingsGroup.Container>
<SettingsGroup.Container>
<SettingsGroup.Body>
<SettingsGroup.Title>SSH</SettingsGroup.Title>
<div className="space-y-3">
{sshCopy}
<p>
Read our{' '}
<Link
to="https://docs.oxide.computer/guides/deploying-workloads#_access_via_ssh"
className="link-with-underline"
target="_blank"
rel="noreferrer"
>
SSH guide
</Link>{' '}
to learn more.
</p>
</div>
</SettingsGroup.Body>
</SettingsGroup.Container>
</div>
)
}
1 change: 1 addition & 0 deletions app/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ export const routes = createRoutesFromElements(
<Route
path="connect"
element={<ConnectTab />}
loader={ConnectTab.loader}
handle={{ crumb: 'Connect' }}
/>
</Route>
Expand Down
Loading