ipn/config: add RelayServerPort and RelayServerStaticEndpoints to config file (#18300)
This commit is contained in:
+17
@@ -52,6 +52,15 @@ type ConfigVAlpha struct {
|
||||
// should advertise amongst its wireguard endpoints.
|
||||
StaticEndpoints []netip.AddrPort `json:",omitempty"`
|
||||
|
||||
// RelayServerPort is the UDP port for the relay server to bind to.
|
||||
// A value of 0 will pick a random unused port. Nil disables relay server.
|
||||
RelayServerPort *uint16 `json:",omitzero"`
|
||||
|
||||
// RelayServerStaticEndpoints are static IP:port endpoints to advertise
|
||||
// as candidates for relay connections. Only relevant when RelayServerPort
|
||||
// is non-nil.
|
||||
RelayServerStaticEndpoints []netip.AddrPort `json:",omitempty"`
|
||||
|
||||
// TODO(bradfitz,maisem): future something like:
|
||||
// Profile map[string]*Config // keyed by alice@gmail.com, corp.com (TailnetSID)
|
||||
}
|
||||
@@ -166,5 +175,13 @@ func (c *ConfigVAlpha) ToPrefs() (MaskedPrefs, error) {
|
||||
if c.AdvertiseServices != nil {
|
||||
mp.AdvertiseServices = c.AdvertiseServices
|
||||
}
|
||||
mp.RelayServerPortSet = true
|
||||
mp.RelayServerStaticEndpointsSet = true
|
||||
if c.RelayServerPort != nil {
|
||||
mp.RelayServerPort = c.RelayServerPort
|
||||
}
|
||||
if c.RelayServerStaticEndpoints != nil {
|
||||
mp.RelayServerStaticEndpoints = c.RelayServerStaticEndpoints
|
||||
}
|
||||
return mp, nil
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ package ipn
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"reflect"
|
||||
"slices"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -64,3 +66,123 @@ func TestConfigVAlpha_ToPrefs_AdvertiseRoutes(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigVAlphaToPrefs(t *testing.T) {
|
||||
aps := func(t *testing.T, strs ...string) (ret []netip.AddrPort) {
|
||||
t.Helper()
|
||||
for _, s := range strs {
|
||||
n, err := netip.ParseAddrPort(s)
|
||||
if err != nil {
|
||||
t.Fatalf("parse AddrPort %q: %v", s, err)
|
||||
}
|
||||
ret = append(ret, n)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
cfg *ConfigVAlpha
|
||||
want MaskedPrefs
|
||||
}{
|
||||
{
|
||||
name: "nil_config",
|
||||
cfg: nil,
|
||||
want: MaskedPrefs{},
|
||||
},
|
||||
{
|
||||
name: "relay_server_port_and_static_endpoints",
|
||||
cfg: &ConfigVAlpha{
|
||||
RelayServerPort: new(uint16(12345)),
|
||||
RelayServerStaticEndpoints: aps(t, "[2001:db8::1]:40000", "192.0.2.1:40000"),
|
||||
},
|
||||
want: MaskedPrefs{
|
||||
Prefs: Prefs{
|
||||
RelayServerPort: new(uint16(12345)),
|
||||
RelayServerStaticEndpoints: aps(t, "[2001:db8::1]:40000", "192.0.2.1:40000"),
|
||||
},
|
||||
RelayServerPortSet: true,
|
||||
RelayServerStaticEndpointsSet: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
// Port 0 means "pick a random unused port"; it is
|
||||
// distinct from a nil port which disables the relay
|
||||
// server. The zero value must be propagated.
|
||||
name: "relay_server_port_zero_is_random_not_disabled",
|
||||
cfg: &ConfigVAlpha{
|
||||
RelayServerPort: new(uint16(0)),
|
||||
},
|
||||
want: MaskedPrefs{
|
||||
Prefs: Prefs{
|
||||
RelayServerPort: new(uint16(0)),
|
||||
},
|
||||
RelayServerPortSet: true,
|
||||
RelayServerStaticEndpointsSet: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "only_static_endpoints_set",
|
||||
cfg: &ConfigVAlpha{
|
||||
RelayServerStaticEndpoints: aps(t, "192.0.2.1:40000"),
|
||||
},
|
||||
want: MaskedPrefs{
|
||||
Prefs: Prefs{
|
||||
RelayServerStaticEndpoints: aps(t, "192.0.2.1:40000"),
|
||||
},
|
||||
RelayServerPortSet: true,
|
||||
RelayServerStaticEndpointsSet: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
// Both fields nil but masks set: the config file is the
|
||||
// source of truth, so this disables any previously
|
||||
// configured relay server.
|
||||
name: "both_nil_disables_relay_server",
|
||||
cfg: &ConfigVAlpha{},
|
||||
want: MaskedPrefs{
|
||||
RelayServerPortSet: true,
|
||||
RelayServerStaticEndpointsSet: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
// An empty (non-nil) static endpoints slice is treated as
|
||||
// "advertise no static endpoints", disabling them.
|
||||
name: "empty_static_endpoints_disables",
|
||||
cfg: &ConfigVAlpha{
|
||||
RelayServerStaticEndpoints: []netip.AddrPort{},
|
||||
},
|
||||
want: MaskedPrefs{
|
||||
Prefs: Prefs{
|
||||
RelayServerStaticEndpoints: []netip.AddrPort{},
|
||||
},
|
||||
RelayServerPortSet: true,
|
||||
RelayServerStaticEndpointsSet: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := tt.cfg.ToPrefs()
|
||||
if err != nil {
|
||||
t.Fatalf("ToPrefs() unexpected error: %v", err)
|
||||
}
|
||||
// Compare only the relay-server-related fields rather than
|
||||
// the whole MaskedPrefs, since ToPrefs populates many
|
||||
// unrelated default fields (e.g. WantRunning).
|
||||
if got.RelayServerPortSet != tt.want.RelayServerPortSet {
|
||||
t.Errorf("RelayServerPortSet = %v; want %v", got.RelayServerPortSet, tt.want.RelayServerPortSet)
|
||||
}
|
||||
if got.RelayServerStaticEndpointsSet != tt.want.RelayServerStaticEndpointsSet {
|
||||
t.Errorf("RelayServerStaticEndpointsSet = %v; want %v", got.RelayServerStaticEndpointsSet, tt.want.RelayServerStaticEndpointsSet)
|
||||
}
|
||||
if !reflect.DeepEqual(got.RelayServerPort, tt.want.RelayServerPort) {
|
||||
t.Errorf("RelayServerPort = %v; want %v", got.RelayServerPort, tt.want.RelayServerPort)
|
||||
}
|
||||
if !slices.Equal(got.RelayServerStaticEndpoints, tt.want.RelayServerStaticEndpoints) {
|
||||
t.Errorf("RelayServerStaticEndpoints = %v; want %v", got.RelayServerStaticEndpoints, tt.want.RelayServerStaticEndpoints)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7490,6 +7490,78 @@ func TestConfigFileReload(t *testing.T) {
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "enable_relay_server",
|
||||
initial: &conffile.Config{
|
||||
Parsed: ipn.ConfigVAlpha{
|
||||
Version: "alpha0",
|
||||
},
|
||||
},
|
||||
updated: &conffile.Config{
|
||||
Parsed: ipn.ConfigVAlpha{
|
||||
Version: "alpha0",
|
||||
RelayServerPort: new(uint16(12345)),
|
||||
RelayServerStaticEndpoints: []netip.AddrPort{netip.MustParseAddrPort("[2001:db8::1]:40000")},
|
||||
},
|
||||
},
|
||||
checkFn: func(t *testing.T, b *LocalBackend) {
|
||||
pv := b.Prefs()
|
||||
if port, ok := pv.RelayServerPort().GetOk(); !ok || port != 12345 {
|
||||
t.Errorf("RelayServerPort = (%d, %v); want (12345, true)", port, ok)
|
||||
}
|
||||
if got := pv.RelayServerStaticEndpoints().AsSlice(); !slices.Equal(got, []netip.AddrPort{netip.MustParseAddrPort("[2001:db8::1]:40000")}) {
|
||||
t.Errorf("RelayServerStaticEndpoints = %v; want [[2001:db8::1]:40000]", got)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
// Disabling: a config that omits the relay server fields
|
||||
// must clear any previously configured values, because
|
||||
// ToPrefs sets the masks unconditionally.
|
||||
name: "disable_relay_server",
|
||||
initial: &conffile.Config{
|
||||
Parsed: ipn.ConfigVAlpha{
|
||||
Version: "alpha0",
|
||||
RelayServerPort: new(uint16(12345)),
|
||||
RelayServerStaticEndpoints: []netip.AddrPort{netip.MustParseAddrPort("[2001:db8::1]:40000")},
|
||||
},
|
||||
},
|
||||
updated: &conffile.Config{
|
||||
Parsed: ipn.ConfigVAlpha{
|
||||
Version: "alpha0",
|
||||
},
|
||||
},
|
||||
checkFn: func(t *testing.T, b *LocalBackend) {
|
||||
pv := b.Prefs()
|
||||
if _, ok := pv.RelayServerPort().GetOk(); ok {
|
||||
t.Errorf("RelayServerPort = %v; want disabled", pv.RelayServerPort())
|
||||
}
|
||||
if got := pv.RelayServerStaticEndpoints().AsSlice(); len(got) != 0 {
|
||||
t.Errorf("RelayServerStaticEndpoints = %v; want empty", got)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "change_relay_server_port",
|
||||
initial: &conffile.Config{
|
||||
Parsed: ipn.ConfigVAlpha{
|
||||
Version: "alpha0",
|
||||
RelayServerPort: new(uint16(12345)),
|
||||
},
|
||||
},
|
||||
updated: &conffile.Config{
|
||||
Parsed: ipn.ConfigVAlpha{
|
||||
Version: "alpha0",
|
||||
RelayServerPort: new(uint16(54321)),
|
||||
},
|
||||
},
|
||||
checkFn: func(t *testing.T, b *LocalBackend) {
|
||||
pv := b.Prefs()
|
||||
if port, ok := pv.RelayServerPort().GetOk(); !ok || port != 54321 {
|
||||
t.Errorf("RelayServerPort = (%d, %v); want (54321, true)", port, ok)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
|
||||
Reference in New Issue
Block a user