handle ssh tunnel error

This commit is contained in:
Jan Prochazka 2021-02-13 12:46:37 +01:00
parent 0d1a6e96f3
commit 521199ee1a
4 changed files with 68 additions and 15 deletions

View File

@ -7,7 +7,10 @@ const { getSshTunnelProxy } = require('./sshTunnelProxy');
async function connectUtility(driver, storedConnection) {
let connection = decryptConnection(storedConnection);
if (connection.useSshTunnel) {
const localPort = await getSshTunnelProxy(connection);
const tunnel = await getSshTunnelProxy(connection);
if (tunnel.state == 'error') {
throw new Error(tunnel.message);
}
// const sshConfig = {
// endHost: connection.sshHost || '',
// endPort: connection.sshPort || 22,
@ -35,7 +38,7 @@ async function connectUtility(driver, storedConnection) {
connection = {
...connection,
server: '127.0.0.1',
port: localPort,
port: tunnel.localPort,
};
}

View File

@ -8,7 +8,16 @@ const platformInfo = require('./platformInfo');
const sshConnectionCache = {};
const sshTunnelCache = {};
const CONNECTION_FIELDS = ['sshHost', 'sshPort', 'sshLogin', 'sshPassword'];
const CONNECTION_FIELDS = [
'sshHost',
'sshPort',
'sshLogin',
'sshPassword',
'sshMode',
'sshKeyFile',
'sshBastionHost',
'sshKeyFilePassword',
];
const TUNNEL_FIELDS = [...CONNECTION_FIELDS, 'server', 'port'];
async function getSshConnection(connection) {
@ -38,7 +47,7 @@ async function getSshConnection(connection) {
async function getSshTunnel(connection) {
const sshConn = await getSshConnection(connection);
const tunnelCacheKey = stableStringify(_.pick(connection, TUNNEL_FIELDS));
if (sshTunnelCache[tunnelCacheKey]) return sshTunnelCache[tunnelCacheKey].localPort;
if (sshTunnelCache[tunnelCacheKey]) return sshTunnelCache[tunnelCacheKey];
const localPort = await portfinder.getPortPromise({ port: 10000, stopPort: 60000 });
// workaround for `getPortPromise` not releasing the port quickly enough
@ -48,17 +57,24 @@ async function getSshTunnel(connection) {
toPort: connection.port,
toHost: connection.server,
};
const tunnel = await sshConn.forward(tunnelConfig);
console.log(
`Created SSH tunnel to ${connection.sshHost}-${connection.server}:${connection.port}, using local port ${localPort}`
);
try {
const tunnel = await sshConn.forward(tunnelConfig);
console.log(
`Created SSH tunnel to ${connection.sshHost}-${connection.server}:${connection.port}, using local port ${localPort}`
);
sshTunnelCache[tunnelCacheKey] = {
tunnel,
localPort,
};
return localPort;
sshTunnelCache[tunnelCacheKey] = {
state: 'ok',
localPort,
};
return sshTunnelCache[tunnelCacheKey];
} catch (err) {
// error is not cached
return {
state: 'error',
message: err.message,
};
}
}
module.exports = {

View File

@ -20,6 +20,7 @@ import { FormProvider, useForm } from '../utility/FormProvider';
import { TabControl, TabPage } from '../widgets/TabControl';
import { usePlatformInfo } from '../utility/metadataLoaders';
import getElectron from '../utility/getElectron';
import { FormFieldTemplateLarge } from '../utility/formStyle';
// import FormikForm from '../utility/FormikForm';
function DriverFields({ extensions }) {
@ -154,7 +155,10 @@ export default function ConnectionModal({ modalState, connection = undefined })
return (
<ModalBase modalState={modalState}>
<ModalHeader modalState={modalState}>{connection ? 'Edit connection' : 'Add connection'}</ModalHeader>
<FormProvider initialValues={connection || { server: 'localhost', engine: 'mssql@dbgate-plugin-mssql' }}>
<FormProvider
initialValues={connection || { server: 'localhost', engine: 'mssql@dbgate-plugin-mssql' }}
template={FormFieldTemplateLarge}
>
<ModalContent noPadding>
<TabControl isInline>
<TabPage label="Main" key="main">

View File

@ -52,3 +52,33 @@ export function FormFieldTemplateTiny({ label, children, type }) {
</FormRowTiny>
);
}
export const FormRowLarge = styled.div`
margin: 5px;
`;
export const FormLabelLarge = styled.div`
color: ${props => props.theme.manager_font3};
`;
export const FormValueLarge = styled.div`
margin-left: 15px;
margin-top: 3px;
`;
export function FormFieldTemplateLarge({ label, children, type }) {
const theme = useTheme();
if (type == 'checkbox') {
return (
<FormRowTiny>
{children} {label}
</FormRowTiny>
);
}
return (
<FormRowTiny>
<FormLabelTiny theme={theme}>{label}</FormLabelTiny>
<FormValueTiny>{children}</FormValueTiny>
</FormRowTiny>
);
}