From 976d9410774efc0f12eadc0ea1ced812791ef35e Mon Sep 17 00:00:00 2001 From: Chris Hoage Date: Sun, 16 Feb 2025 17:45:27 -0800 Subject: [PATCH] allow port to be configured with direct assignment Signed-off-by: Christopher Hoage --- app.go | 13 +++++++++++++ module.go | 17 +++++++++++++---- module_test.go | 28 ++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/app.go b/app.go index dbcc6d2..7207a2d 100644 --- a/app.go +++ b/app.go @@ -66,6 +66,8 @@ type Node struct { // Hostname is the hostname to use when registering the node. Hostname string `json:"hostname,omitempty" caddy:"namespace=tailscale.hostname"` + Port uint16 `json:"port,omitempty" caddy:"namespace=tailscale.port"` + // StateDir specifies the state directory for the node. StateDir string `json:"state_dir,omitempty" caddy:"namespace=tailscale.state_dir"` @@ -190,6 +192,17 @@ func parseNodeConfig(d *caddyfile.Dispenser) (Node, error) { } else { node.Ephemeral = opt.NewBool(true) } + case "port": + if segment.NextArg() { + v, err := strconv.ParseUint(segment.Val(), 10, 16) + if err != nil { + return node, segment.WrapErr(err) + } + node.Port = uint16(v) + } else { + node.Port = 0 + } + case "hostname": if !segment.NextArg() { return node, segment.ArgErr() diff --git a/module.go b/module.go index 2a5e67d..5b7bc40 100644 --- a/module.go +++ b/module.go @@ -49,12 +49,12 @@ func getTCPListener(c context.Context, network string, host string, portRange st if !ok { return nil, fmt.Errorf("context is not a caddy.Context: %T", c) } - + na, err := caddy.ParseNetworkAddress(caddy.JoinNetworkAddress(network, host, portRange)) if err != nil { return nil, err } - + addr := na.JoinHostPort(portOffset) network, host, port, err := caddy.SplitNetworkAddress(addr) if err != nil { @@ -82,7 +82,7 @@ func getTLSListener(c context.Context, network string, host string, portRange st if err != nil { return nil, err } - + addr := na.JoinHostPort(portOffset) network, host, port, err := caddy.SplitNetworkAddress(addr) if err != nil { @@ -121,7 +121,7 @@ func getUDPListener(c context.Context, network string, host string, portRange st if err != nil { return nil, err } - + addr := na.JoinHostPort(portOffset) network, host, port, err := caddy.SplitNetworkAddress(addr) if err != nil { @@ -183,6 +183,7 @@ func getNode(ctx caddy.Context, name string) (*tailscaleNode, error) { }, Ephemeral: getEphemeral(name, app), RunWebClient: getWebUI(name, app), + Port: getPort(name, app), } if s.AuthKey, err = getAuthKey(name, app); err != nil { @@ -268,6 +269,14 @@ func getHostname(name string, app *App) (string, error) { return name, nil } +func getPort(name string, app *App) uint16 { + if node, ok := app.Nodes[name]; ok { + return node.Port + } + + return 0 +} + func getStateDir(name string, app *App) (string, error) { if node, ok := app.Nodes[name]; ok { if node.StateDir != "" { diff --git a/module_test.go b/module_test.go index 107be91..26ccdb1 100644 --- a/module_test.go +++ b/module_test.go @@ -221,6 +221,34 @@ func Test_GetHostname(t *testing.T) { } } +func Test_GetPort(t *testing.T) { + app := &App{ + Nodes: map[string]Node{ + "empty": {}, + "port": {Port: 3000}, + }, + } + if err := app.Provision(caddy.Context{}); err != nil { + t.Fatal(err) + } + + got := getPort("noconfig", &App{}) + if want := uint16(0); got != want { + t.Errorf("GetPort() = %v, want %v", got, want) + } + + got = getPort("empty", app) + if want := uint16(0); got != want { + t.Errorf("GetPort() = %v, want %v", got, want) + } + + got = getPort("port", app) + if want := uint16(3000); got != want { + t.Errorf("GetPort() = %v, want %v", got, want) + } + +} + func Test_GetStateDir(t *testing.T) { const nodeName = "node" configDir := must.Get(os.UserConfigDir())