mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Let OS allocate port number
Port availability might be tricky if some port is already in use on the 'all' interface '0.0.0.0'. The proposed solution is to let the OS allocate the port for us using 0 as port specifier : - first create a server instance to allocate a port number - save port number - close the server - return the port number to the caller This should be safe granted the OS doesn't reuse the port numbers on consecutive port allocations. see : - about Node.js Net module : https://nodejs.org/docs/latest-v12.x/api/net.html#net_server_listen_port_host_backlog_callback - about safety around reusing port number : https://unix.stackexchange.com/a/132524 Signed-off-by: Alexis Deruelle <alexis.deruelle@gmail.com>
This commit is contained in:
parent
98f250cfc4
commit
585983f6b6
@ -2,13 +2,10 @@ import { EventEmitter } from 'events'
|
||||
|
||||
class MockServer extends EventEmitter {
|
||||
listen = jest.fn((obj) => {
|
||||
if(obj.port < 9003) {
|
||||
this.emit('error', new Error("fail!"))
|
||||
} else {
|
||||
this.emit('listening', {})
|
||||
}
|
||||
this.emit('listening', {})
|
||||
return this
|
||||
})
|
||||
address = () => { return { port: 12345 }}
|
||||
unref = jest.fn()
|
||||
close = jest.fn((cb) => {
|
||||
cb()
|
||||
@ -29,11 +26,7 @@ describe("getFreePort", () => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("fails for an invalid range", async () => {
|
||||
return expect(port.getFreePort(1, 2)).rejects.toMatch('free port')
|
||||
})
|
||||
|
||||
it("finds the next free port", async () => {
|
||||
return expect(port.getFreePort(9000, 9005)).resolves.toBe(9003)
|
||||
return expect(port.getFreePort()).resolves.toEqual(expect.any(Number))
|
||||
})
|
||||
})
|
||||
|
||||
@ -135,7 +135,7 @@ export class ContextHandler {
|
||||
|
||||
let serverPort: number = null
|
||||
try {
|
||||
serverPort = await getFreePort(49901, 65535)
|
||||
serverPort = await getFreePort()
|
||||
} catch(error) {
|
||||
logger.error(error)
|
||||
throw(error)
|
||||
|
||||
@ -48,7 +48,7 @@ async function main() {
|
||||
let port: number = null
|
||||
// find free port
|
||||
try {
|
||||
port = await getFreePort(49152, 65535)
|
||||
port = await getFreePort()
|
||||
} catch (error) {
|
||||
logger.error(error)
|
||||
await dialog.showErrorBox("Lens Error", "Could not find a free port for the cluster proxy")
|
||||
|
||||
@ -1,27 +1,30 @@
|
||||
import logger from "./logger"
|
||||
import { createServer } from "net"
|
||||
import { AddressInfo } from "net"
|
||||
|
||||
// Adapted from https://gist.github.com/mikeal/1840641#gistcomment-2896667
|
||||
function checkPort(port: number) {
|
||||
const getNextAvailablePort = () => {
|
||||
logger.debug("getNextAvailablePort() start")
|
||||
const server = createServer()
|
||||
server.unref()
|
||||
return new Promise((resolve, reject) =>
|
||||
return new Promise<number>((resolve, reject) =>
|
||||
server
|
||||
.on('error', error => reject(error))
|
||||
.on('listening', () => server.close(() => resolve(port)))
|
||||
.listen({host: "0.0.0.0", port: port}))
|
||||
.on('error', (error: any) => reject(error))
|
||||
.on('listening', () => {
|
||||
logger.debug("*** server listening event ***")
|
||||
const _port = (server.address() as AddressInfo).port
|
||||
server.close(() => resolve(_port))
|
||||
})
|
||||
.listen({host: "127.0.0.1", port: 0}))
|
||||
}
|
||||
|
||||
export async function getFreePort(firstPort: number, lastPort: number): Promise<number> {
|
||||
let port = firstPort
|
||||
|
||||
while(true) {
|
||||
try {
|
||||
logger.debug("Checking port " + port + " availability ...")
|
||||
await checkPort(port)
|
||||
return(port)
|
||||
} catch(error) {
|
||||
if(++port > lastPort) throw("Could not find a free port")
|
||||
}
|
||||
export const getFreePort = async () => {
|
||||
logger.debug("getFreePort() start")
|
||||
let freePort: number = null
|
||||
try {
|
||||
freePort = await getNextAvailablePort()
|
||||
logger.debug("got port : " + freePort)
|
||||
} catch(error) {
|
||||
throw("getNextAvailablePort() threw: '" + error + "'")
|
||||
}
|
||||
return freePort
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ class PortForward {
|
||||
}
|
||||
|
||||
public async start() {
|
||||
this.localPort = await getFreePort(8000, 9999)
|
||||
this.localPort = await getFreePort()
|
||||
const kubectlBin = await bundledKubectl.kubectlPath()
|
||||
const args = [
|
||||
"--kubeconfig", this.kubeConfig,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user