Skip to content

Commit 4160539

Browse files
committed
Support a random port for the local-run
This allows users to run multiple local-runs without picking out ports themselves. Signed-off-by: Alex Ellis (OpenFaaS Ltd) <[email protected]>
1 parent cb0c41e commit 4160539

File tree

1 file changed

+38
-4
lines changed

1 file changed

+38
-4
lines changed

commands/local_run.go

+38-4
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import (
55
"fmt"
66
"io"
77
"log"
8+
"net"
89
"os"
910
"path/filepath"
11+
"strconv"
1012
"strings"
1113
"syscall"
1214

@@ -58,9 +60,12 @@ services deployed within your OpenFaaS cluster.`,
5860
# Run on a custom port
5961
faas-cli local-run stronghash --port 8081
6062
63+
# Run on a random port
64+
faas-cli local-run -p 0
65+
6166
# Use a custom YAML file other than stack.yml
6267
faas-cli local-run stronghash -f ./stronghash.yml
63-
`,
68+
`,
6469
PreRunE: func(cmd *cobra.Command, args []string) error {
6570
if len(args) > 1 {
6671
return fmt.Errorf("only one function name is allowed")
@@ -77,7 +82,7 @@ services deployed within your OpenFaaS cluster.`,
7782

7883
cmd.Flags().BoolVar(&opts.print, "print", false, "Print the docker command instead of running it")
7984
cmd.Flags().BoolVar(&opts.build, "build", true, "Build function prior to local-run")
80-
cmd.Flags().IntVarP(&opts.port, "port", "p", 8080, "port to bind the function to")
85+
cmd.Flags().IntVarP(&opts.port, "port", "p", 8080, "port to bind the function to, set to \"0\" to use a random port")
8186
cmd.Flags().Var(&tagFormat, "tag", "Override latest tag on function Docker image, accepts 'digest', 'sha', 'branch', or 'describe', or 'latest'")
8287

8388
cmd.Flags().StringVar(&opts.network, "network", "", "connect function to an existing network, use 'host' to access other process already running on localhost. When using this, '--port' is ignored, if you have port collisions, you may change the port using '-e port=NEW_PORT'")
@@ -123,7 +128,7 @@ func localRunExec(cmd *cobra.Command, args []string, ctx context.Context) error
123128
name = args[0]
124129
}
125130

126-
return runFunction(ctx, name, opts, args)
131+
return runFunction(ctx, name, opts)
127132

128133
}
129134

@@ -149,7 +154,7 @@ func localBuild(cmd *cobra.Command, args []string) error {
149154
return nil
150155
}
151156

152-
func runFunction(ctx context.Context, name string, opts runOptions, args []string) error {
157+
func runFunction(ctx context.Context, name string, opts runOptions) error {
153158
var services *stack.Services
154159

155160
if len(name) == 0 {
@@ -209,6 +214,14 @@ func runFunction(ctx context.Context, name string, opts runOptions, args []strin
209214
// Enable local jwt auth by default
210215
opts.extraEnv["jwt_auth_local"] = "true"
211216

217+
if opts.port == 0 {
218+
randomPort, err := getPort()
219+
if err != nil {
220+
return err
221+
}
222+
opts.port = randomPort
223+
}
224+
212225
cmd, err := buildDockerRun(ctx, name, function, opts)
213226
if err != nil {
214227
return err
@@ -270,6 +283,27 @@ func runFunction(ctx context.Context, name string, opts runOptions, args []strin
270283
return errGrp.Wait()
271284
}
272285

286+
func getPort() (int, error) {
287+
288+
l, err := net.Listen("tcp", ":0")
289+
if err != nil {
290+
return 0, err
291+
}
292+
293+
l.Close()
294+
295+
_, port, err := net.SplitHostPort(l.Addr().String())
296+
if err != nil {
297+
return 0, err
298+
}
299+
300+
if port != "" {
301+
return strconv.Atoi(port)
302+
}
303+
304+
return 0, fmt.Errorf("unable to get a port")
305+
}
306+
273307
func removeContainer(name string) {
274308

275309
runDockerRm := exec.Command("docker", "rm", "-f", name)

0 commit comments

Comments
 (0)