TUN-4927: Parameterize region in edge discovery code

This commit is contained in:
Areg Harutyunyan 2021-08-17 13:07:40 -05:00
parent 12ad264eb3
commit 3ef3e7a99a
No known key found for this signature in database
GPG Key ID: 97A3DFFE8E9320B7
6 changed files with 35 additions and 10 deletions

View File

@ -22,6 +22,8 @@ const (
dotServerName = "cloudflare-dns.com" dotServerName = "cloudflare-dns.com"
dotServerAddr = "1.1.1.1:853" dotServerAddr = "1.1.1.1:853"
dotTimeout = 15 * time.Second dotTimeout = 15 * time.Second
logFieldAddress = "address"
) )
// Redeclare network functions so they can be overridden in tests. // Redeclare network functions so they can be overridden in tests.
@ -59,7 +61,9 @@ var friendlyDNSErrorLines = []string{
} }
// EdgeDiscovery implements HA service discovery lookup. // EdgeDiscovery implements HA service discovery lookup.
func edgeDiscovery(log *zerolog.Logger) ([][]*EdgeAddr, error) { func edgeDiscovery(log *zerolog.Logger, srvService string) ([][]*EdgeAddr, error) {
log.Debug().Str("domain", "_"+srvService+"._"+srvProto+"."+srvName).Msg("looking up edge SRV record")
_, addrs, err := netLookupSRV(srvService, srvProto, srvName) _, addrs, err := netLookupSRV(srvService, srvProto, srvName)
if err != nil { if err != nil {
_, fallbackAddrs, fallbackErr := fallbackLookupSRV(srvService, srvProto, srvName) _, fallbackAddrs, fallbackErr := fallbackLookupSRV(srvService, srvProto, srvName)
@ -87,7 +91,7 @@ func edgeDiscovery(log *zerolog.Logger) ([][]*EdgeAddr, error) {
return resolvedAddrPerCNAME, nil return resolvedAddrPerCNAME, nil
} }
func lookupSRVWithDOT(service, proto, name string) (cname string, addrs []*net.SRV, err error) { func lookupSRVWithDOT(string, string, string) (cname string, addrs []*net.SRV, err error) {
// Inspiration: https://github.com/artyom/dot/blob/master/dot.go // Inspiration: https://github.com/artyom/dot/blob/master/dot.go
r := &net.Resolver{ r := &net.Resolver{
PreferGo: true, PreferGo: true,
@ -130,13 +134,13 @@ func ResolveAddrs(addrs []string, log *zerolog.Logger) (resolved []*EdgeAddr) {
for _, addr := range addrs { for _, addr := range addrs {
tcpAddr, err := net.ResolveTCPAddr("tcp", addr) tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil { if err != nil {
log.Error().Msgf("Failed to resolve %s to TCP address, err: %v", addr, err) log.Error().Str(logFieldAddress, addr).Err(err).Msg("failed to resolve to TCP address")
continue continue
} }
udpAddr, err := net.ResolveUDPAddr("udp", addr) udpAddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil { if err != nil {
log.Error().Msgf("Failed to resolve %s to UDP address, err: %v", addr, err) log.Error().Str(logFieldAddress, addr).Err(err).Msg("failed to resolve to UDP address")
continue continue
} }
resolved = append(resolved, &EdgeAddr{ resolved = append(resolved, &EdgeAddr{

View File

@ -25,7 +25,7 @@ func TestEdgeDiscovery(t *testing.T) {
} }
l := zerolog.Nop() l := zerolog.Nop()
addrLists, err := edgeDiscovery(&l) addrLists, err := edgeDiscovery(&l, "")
assert.NoError(t, err) assert.NoError(t, err)
actualAddrSet := map[string]bool{} actualAddrSet := map[string]bool{}
for _, addrs := range addrLists { for _, addrs := range addrLists {

View File

@ -18,8 +18,8 @@ type Regions struct {
// ------------------------------------ // ------------------------------------
// ResolveEdge resolves the Cloudflare edge, returning all regions discovered. // ResolveEdge resolves the Cloudflare edge, returning all regions discovered.
func ResolveEdge(log *zerolog.Logger) (*Regions, error) { func ResolveEdge(log *zerolog.Logger, region string) (*Regions, error) {
edgeAddrs, err := edgeDiscovery(log) edgeAddrs, err := edgeDiscovery(log, getRegionalServiceName(region))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -122,3 +122,12 @@ func (rs *Regions) GiveBack(addr *EdgeAddr) bool {
} }
return rs.region2.GiveBack(addr) return rs.region2.GiveBack(addr)
} }
// Return regionalized service name if `region` isn't empty, otherwise return the global service name for origintunneld
func getRegionalServiceName(region string) string {
if region != "" {
return region + "-" + srvService // Example: `us-origintunneld`
}
return srvService // Global service is just `origintunneld`
}

View File

@ -156,6 +156,18 @@ func TestNewNoResolveBalancesRegions(t *testing.T) {
} }
} }
func TestGetRegionalServiceName(t *testing.T) {
// Empty region should just go to origintunneld
globalServiceName := getRegionalServiceName("")
assert.Equal(t, srvService, globalServiceName)
// Non-empty region should go to the regional origintunneld variant
for _, region := range []string{"us", "pt", "am"} {
regionalServiceName := getRegionalServiceName(region)
assert.Equal(t, region+"-"+srvService, regionalServiceName)
}
}
func RegionsIsBalanced(t *testing.T, rs *Regions) { func RegionsIsBalanced(t *testing.T, rs *Regions) {
delta := rs.region1.AvailableAddrs() - rs.region2.AvailableAddrs() delta := rs.region1.AvailableAddrs() - rs.region2.AvailableAddrs()
assert.True(t, abs(delta) <= 1) assert.True(t, abs(delta) <= 1)

View File

@ -30,8 +30,8 @@ type Edge struct {
// ResolveEdge runs the initial discovery of the Cloudflare edge, finding Addrs that can be allocated // ResolveEdge runs the initial discovery of the Cloudflare edge, finding Addrs that can be allocated
// to connections. // to connections.
func ResolveEdge(log *zerolog.Logger) (*Edge, error) { func ResolveEdge(log *zerolog.Logger, region string) (*Edge, error) {
regions, err := allregions.ResolveEdge(log) regions, err := allregions.ResolveEdge(log, region)
if err != nil { if err != nil {
return new(Edge), err return new(Edge), err
} }

View File

@ -74,7 +74,7 @@ func NewSupervisor(config *TunnelConfig, reconnectCh chan ReconnectSignal, grace
if len(config.EdgeAddrs) > 0 { if len(config.EdgeAddrs) > 0 {
edgeIPs, err = edgediscovery.StaticEdge(config.Log, config.EdgeAddrs) edgeIPs, err = edgediscovery.StaticEdge(config.Log, config.EdgeAddrs)
} else { } else {
edgeIPs, err = edgediscovery.ResolveEdge(config.Log) edgeIPs, err = edgediscovery.ResolveEdge(config.Log, "")
} }
if err != nil { if err != nil {
return nil, err return nil, err