mirror of
https://github.com/balena-io/balena-cli.git
synced 2024-12-28 01:28:51 +00:00
Merge pull request #1180 from balena-io/tunnel-short-uuid
tunnel: allow using partial device uuids
This commit is contained in:
commit
12615cd0dc
@ -20,6 +20,7 @@ import * as _ from 'lodash';
|
|||||||
import { createServer, Server, Socket } from 'net';
|
import { createServer, Server, Socket } from 'net';
|
||||||
import { isArray } from 'util';
|
import { isArray } from 'util';
|
||||||
|
|
||||||
|
import { inferOrSelectDevice } from '../utils/patterns';
|
||||||
import { tunnelConnectionToDevice } from '../utils/tunnel';
|
import { tunnelConnectionToDevice } from '../utils/tunnel';
|
||||||
|
|
||||||
interface Args {
|
interface Args {
|
||||||
@ -128,116 +129,117 @@ export const tunnel: CommandDefinition<Args, Options> = {
|
|||||||
? (options.port as string[])
|
? (options.port as string[])
|
||||||
: [options.port as string];
|
: [options.port as string];
|
||||||
|
|
||||||
return Bluebird.try(() =>
|
return inferOrSelectDevice(params.uuid)
|
||||||
sdk.models.device
|
.then(sdk.models.device.get)
|
||||||
.get(params.uuid)
|
.then(device => {
|
||||||
.then(device => {
|
if (!device.is_online) {
|
||||||
if (!device.is_online) {
|
throw new DeviceIsOfflineError(device.uuid);
|
||||||
throw new DeviceIsOfflineError(params.uuid);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const localListeners = _.chain(ports)
|
const localListeners = _.chain(ports)
|
||||||
.map(mapping => {
|
.map(mapping => {
|
||||||
const regexResult = /^([0-9]+)(?:$|\:(?:([\w\:\.]+)\:|)([0-9]+))$/.exec(
|
const regexResult = /^([0-9]+)(?:$|\:(?:([\w\:\.]+)\:|)([0-9]+))$/.exec(
|
||||||
mapping,
|
mapping,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (regexResult === null) {
|
if (regexResult === null) {
|
||||||
throw new InvalidPortMappingError(mapping);
|
throw new InvalidPortMappingError(mapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
// grab the groups
|
// grab the groups
|
||||||
// tslint:disable-next-line:prefer-const
|
// tslint:disable-next-line:prefer-const
|
||||||
let [, remotePort, localAddress, localPort] = regexResult;
|
let [, remotePort, localAddress, localPort] = regexResult;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!isValidPort(parseInt(localPort, undefined)) ||
|
!isValidPort(parseInt(localPort, undefined)) ||
|
||||||
!isValidPort(parseInt(remotePort, undefined))
|
!isValidPort(parseInt(remotePort, undefined))
|
||||||
) {
|
) {
|
||||||
throw new InvalidPortMappingError(mapping);
|
throw new InvalidPortMappingError(mapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
// default bind to localAddress
|
// default bind to localAddress
|
||||||
if (localAddress == null) {
|
if (localAddress == null) {
|
||||||
localAddress = 'localhost';
|
localAddress = 'localhost';
|
||||||
}
|
}
|
||||||
|
|
||||||
// default use same port number locally as remote
|
// default use same port number locally as remote
|
||||||
if (localPort == null) {
|
if (localPort == null) {
|
||||||
localPort = remotePort;
|
localPort = remotePort;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
localPort: parseInt(localPort, undefined),
|
localPort: parseInt(localPort, undefined),
|
||||||
localAddress,
|
localAddress,
|
||||||
remotePort: parseInt(remotePort, undefined),
|
remotePort: parseInt(remotePort, undefined),
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.map(({ localPort, localAddress, remotePort }) => {
|
.map(({ localPort, localAddress, remotePort }) => {
|
||||||
return tunnelConnectionToDevice(params.uuid, remotePort, sdk)
|
return tunnelConnectionToDevice(device.uuid, remotePort, sdk)
|
||||||
.then(handler =>
|
.then(handler =>
|
||||||
createServer((client: Socket) => {
|
createServer((client: Socket) => {
|
||||||
return handler(client)
|
return handler(client)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logConnection(
|
logConnection(
|
||||||
client.remoteAddress,
|
client.remoteAddress,
|
||||||
client.remotePort,
|
client.remotePort,
|
||||||
client.localAddress,
|
client.localAddress,
|
||||||
client.localPort,
|
client.localPort,
|
||||||
device.vpn_address || '',
|
device.vpn_address || '',
|
||||||
remotePort,
|
remotePort,
|
||||||
);
|
|
||||||
})
|
|
||||||
.catch(err =>
|
|
||||||
logConnection(
|
|
||||||
client.remoteAddress,
|
|
||||||
client.remotePort,
|
|
||||||
client.localAddress,
|
|
||||||
client.localPort,
|
|
||||||
device.vpn_address || '',
|
|
||||||
remotePort,
|
|
||||||
err,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
})
|
||||||
|
.catch(err =>
|
||||||
|
logConnection(
|
||||||
|
client.remoteAddress,
|
||||||
|
client.remotePort,
|
||||||
|
client.localAddress,
|
||||||
|
client.localPort,
|
||||||
|
device.vpn_address || '',
|
||||||
|
remotePort,
|
||||||
|
err,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
server =>
|
||||||
|
new Bluebird.Promise<Server>((resolve, reject) => {
|
||||||
|
server.on('error', reject);
|
||||||
|
server.listen(localPort, localAddress, () => {
|
||||||
|
resolve(server);
|
||||||
|
});
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.then(
|
.then(() => {
|
||||||
server =>
|
logger.logInfo(
|
||||||
new Bluebird.Promise<Server>((resolve, reject) => {
|
` - tunnelling ${localAddress}:${localPort} to ${
|
||||||
server.on('error', reject);
|
device.uuid
|
||||||
server.listen(localPort, localAddress, () => {
|
}:${remotePort}`,
|
||||||
resolve(server);
|
);
|
||||||
});
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.then(() => {
|
|
||||||
logger.logInfo(
|
|
||||||
` - tunnelling ${localAddress}:${localPort} to device:${remotePort}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.catch((err: Error) => {
|
.catch((err: Error) => {
|
||||||
logger.logWarn(
|
logger.logWarn(
|
||||||
` - not tunnelling ${localAddress}:${localPort} to device:${remotePort}, failed ${JSON.stringify(
|
` - not tunnelling ${localAddress}:${localPort} to ${
|
||||||
err.message,
|
device.uuid
|
||||||
)}`,
|
}:${remotePort}, failed ${JSON.stringify(err.message)}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.value();
|
.value();
|
||||||
|
|
||||||
return Bluebird.all(localListeners);
|
return Bluebird.all(localListeners);
|
||||||
})
|
})
|
||||||
.then(results => {
|
.then(results => {
|
||||||
if (!results.includes(true)) {
|
if (!results.includes(true)) {
|
||||||
throw new Error('No ports are valid for tunnelling');
|
throw new Error('No ports are valid for tunnelling');
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.logInfo('Waiting for connections...');
|
logger.logInfo('Waiting for connections...');
|
||||||
}),
|
})
|
||||||
).nodeify(done);
|
.nodeify(done);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user