Skip to content

Commit

Permalink
Merge pull request #279 from rancher/feature/random-api-port
Browse files Browse the repository at this point in the history
[Feature] Choose random API Port by default
  • Loading branch information
iwilltry42 authored Jun 12, 2020
2 parents 5643b4e + d6b5d4d commit 178fe6d
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 3 deletions.
2 changes: 1 addition & 1 deletion cmd/create/createCluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func NewCmdCreateCluster() *cobra.Command {
/*********
* Flags *
*********/
cmd.Flags().StringP("api-port", "a", k3d.DefaultAPIPort, "Specify the Kubernetes API server port exposed on the LoadBalancer (Format: `--api-port [HOST:]HOSTPORT`)\n - Example: `k3d create -m 3 -a 0.0.0.0:6550`")
cmd.Flags().StringP("api-port", "a", "random", "Specify the Kubernetes API server port exposed on the LoadBalancer (Format: `--api-port [HOST:]HOSTPORT`)\n - Example: `k3d create -m 3 -a 0.0.0.0:6550`")
cmd.Flags().IntP("masters", "m", 1, "Specify how many masters you want to create")
cmd.Flags().IntP("workers", "w", 0, "Specify how many workers you want to create")
cmd.Flags().StringP("image", "i", fmt.Sprintf("%s:%s", k3d.DefaultK3sImageRepo, version.GetK3sVersion(false)), "Specify k3s image that you want to use for the nodes")
Expand Down
33 changes: 32 additions & 1 deletion cmd/util/ports.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,27 @@ func ParseAPIPort(portString string) (k3d.ExposeAPI, error) {
}

// Verify 'port' is an integer and within port ranges
if exposeAPI.Port == "" || exposeAPI.Port == "random" {
log.Debugf("API-Port Mapping didn't specify hostPort, choosing one randomly...")
freePort, err := GetFreePort()
if err != nil || freePort == 0 {
log.Warnf("Failed to get random free port:\n%+v", err)
log.Warnf("Falling back to default port %s (may be blocked though)...", k3d.DefaultAPIPort)
exposeAPI.Port = k3d.DefaultAPIPort
} else {
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")
return exposeAPI, err
}

if p < 0 || p > 65535 {
log.Errorln("Failed to parse API Port specification")
return exposeAPI, fmt.Errorf("port value '%d' out of range", p)
return exposeAPI, fmt.Errorf("Port value '%d' out of range", p)
}

return exposeAPI, nil
Expand All @@ -72,3 +85,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
}
2 changes: 1 addition & 1 deletion tests/test_basic.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ source "$CURR_DIR/common.sh"

info "Creating two clusters..."
$EXE create cluster c1 --wait --timeout 60s --api-port 6443 || failed "could not create cluster c1"
$EXE create cluster c2 --wait --timeout 60s --api-port 6444 || failed "could not create cluster c2"
$EXE create cluster c2 --wait --timeout 60s || failed "could not create cluster c2"

info "Checking that we can get both clusters..."
check_cluster_count 2
Expand Down

0 comments on commit 178fe6d

Please sign in to comment.