Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions internal/boxcli/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type serviceUpFlags struct {
background bool
processComposeFile string
processComposeFlags []string
pcport int
}

type serviceStopFlags struct {
Expand All @@ -38,6 +39,8 @@ func (flags *serviceUpFlags) register(cmd *cobra.Command) {
&flags.background, "background", "b", false, "run service in background")
cmd.Flags().StringArrayVar(
&flags.processComposeFlags, "pcflags", []string{}, "pass flags directly to process compose")
cmd.Flags().IntVarP(
&flags.pcport, "pcport", "p", 0, "specify the port for process-compose to use. You can also set the pcport by exporting DEVBOX_PC_PORT_NUM")
}

func (flags *serviceStopFlags) register(cmd *cobra.Command) {
Expand Down Expand Up @@ -245,6 +248,10 @@ func startProcessManager(
return err
}

if flags.pcport < 0 {
return errors.Errorf("invalid pcport %d: ports cannot be less than 0", flags.pcport)
}

box, err := devbox.Open(&devopt.Opts{
Dir: servicesFlags.config.path,
Env: env,
Expand All @@ -261,8 +268,9 @@ func startProcessManager(
servicesFlags.runInCurrentShell,
args,
devopt.ProcessComposeOpts{
Background: flags.background,
ExtraFlags: flags.processComposeFlags,
Background: flags.background,
ExtraFlags: flags.processComposeFlags,
ProcessComposePort: flags.pcport,
},
)
}
5 changes: 3 additions & 2 deletions internal/devbox/devopt/devboxopts.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ type Opts struct {
}

type ProcessComposeOpts struct {
ExtraFlags []string
Background bool
ExtraFlags []string
Background bool
ProcessComposePort int
}

type GenerateOpts struct {
Expand Down
11 changes: 8 additions & 3 deletions internal/devbox/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package devbox
import (
"context"
"fmt"
"strconv"
"text/tabwriter"

"go.jetpack.io/devbox/internal/boxcli/usererr"
Expand Down Expand Up @@ -217,6 +218,9 @@ func (d *Devbox) StartProcessManager(
for _, flag := range processComposeOpts.ExtraFlags {
args = append(args, "--pcflags", flag)
}
if processComposeOpts.ProcessComposePort != 0 {
args = append(args, "--pcport", strconv.Itoa(processComposeOpts.ProcessComposePort))
}

return d.runDevboxServicesScript(ctx, args)
}
Expand Down Expand Up @@ -254,9 +258,10 @@ func (d *Devbox) StartProcessManager(
svcs,
d.projectDir,
services.ProcessComposeOpts{
BinPath: processComposeBinPath,
Background: processComposeOpts.Background,
ExtraFlags: processComposeOpts.ExtraFlags,
BinPath: processComposeBinPath,
Background: processComposeOpts.Background,
ExtraFlags: processComposeOpts.ExtraFlags,
ProcessComposePort: processComposeOpts.ProcessComposePort,
},
)
}
Expand Down
12 changes: 6 additions & 6 deletions internal/services/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@ type globalProcessComposeConfig struct {
}

type ProcessComposeOpts struct {
BinPath string
ExtraFlags []string
Background bool
BinPath string
ExtraFlags []string
Background bool
ProcessComposePort int
}

func newGlobalProcessComposeConfig() *globalProcessComposeConfig {
Expand Down Expand Up @@ -128,10 +129,9 @@ func StartProcessManager(
config := readGlobalProcessComposeJSON(configFile)
config.File = configFile

// Get the port to use for this project
port, err := getAvailablePort()
port, err := selectPort(processComposeConfig.ProcessComposePort)
if err != nil {
return err
return fmt.Errorf("failed to select port: %v", err)
}

// Start building the process-compose command
Expand Down
41 changes: 33 additions & 8 deletions internal/services/ports.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package services

import (
"fmt"
"net"
"os"
"strconv"

"github.com/pkg/errors"
)
Expand Down Expand Up @@ -33,17 +36,11 @@ var disallowedPorts = map[int]string{

func getAvailablePort() (int, error) {
get := func() (int, error) {
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
port, err := isPortAvailable(0)
if err != nil {
return 0, errors.WithStack(err)
}

l, err := net.ListenTCP("tcp", addr)
if err != nil {
return 0, errors.WithStack(err)
}
defer l.Close()
return l.Addr().(*net.TCPAddr).Port, nil
return port, nil
}

for range 1000 {
Expand All @@ -60,6 +57,34 @@ func getAvailablePort() (int, error) {
return 0, errors.New("no available port")
}

func selectPort(configPort int) (int, error) {
if configPort != 0 {
return isPortAvailable(configPort)
}

if portStr, exists := os.LookupEnv("DEVBOX_PC_PORT_NUM"); exists {
port, err := strconv.Atoi(portStr)
if err != nil {
return 0, fmt.Errorf("invalid DEVBOX_PC_PORT_NUM environment variable: %v", err)
}
if port <= 0 {
return 0, fmt.Errorf("invalid DEVBOX_PC_PORT_NUM environment variable: ports cannot be less than 0")
}
return isPortAvailable(port)
}

return getAvailablePort()
}

func isAllowed(port int) bool {
return port > 1024 && disallowedPorts[port] == ""
}

func isPortAvailable(port int) (int, error) {
ln, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", port))
if err != nil {
return 0, fmt.Errorf("port %d is already in use", port)
}
defer ln.Close()
return ln.Addr().(*net.TCPAddr).Port, nil
}
Loading