@ -54,7 +54,16 @@ func ParseAPIPort(portString string) (k3d.ExposeAPI, error) {
}
// Verify 'port' is an integer and within port ranges
if exposeAPI . Port != "" {
if exposeAPI . Port == "" {
log . Debugf ( "API-Port Mapping didn't specify hostPort, choosing one randomly..." )
freePort , err := GetFreePort ( )
if err != nil || freePort == 0 {
log . Errorln ( "Failed to get a free port" )
return exposeAPI , err
}
exposeAPI . Port = strconv . Itoa ( freePort )
log . Debugf ( "Got free port for API: '%d'" , freePort )
}
p , err := strconv . Atoi ( exposeAPI . Port )
if err != nil {
log . Errorln ( "Failed to parse port mapping" )
@ -63,10 +72,7 @@ func ParseAPIPort(portString string) (k3d.ExposeAPI, error) {
if p < 0 || p > 65535 {
log . Errorln ( "Failed to parse API Port specification" )
return exposeAPI , fmt . Errorf ( "port value '%d' out of range" , p )
}
} else {
log . Debugf ( "API-Port Mapping didn't specify hostPort!" )
return exposeAPI , fmt . Errorf ( "Port value '%d' out of range" , p )
}
return exposeAPI , nil
@ -77,3 +83,21 @@ func ParseAPIPort(portString string) (k3d.ExposeAPI, error) {
func ValidatePortMap ( portmap string ) ( string , error ) {
return portmap , nil // TODO: ValidatePortMap: add validation of port mapping
}
// GetFreePort tries to fetch an open port from the OS-Kernel
func GetFreePort ( ) ( int , error ) {
tcpAddress , err := net . ResolveTCPAddr ( "tcp" , "localhost:0" )
if err != nil {
log . Errorln ( "Failed to resolve address" )
return 0 , err
}
tcpListener , err := net . ListenTCP ( "tcp" , tcpAddress )
if err != nil {
log . Errorln ( "Failed to create TCP Listener" )
return 0 , err
}
defer tcpListener . Close ( )
return tcpListener . Addr ( ) . ( * net . TCPAddr ) . Port , nil
}