support multiple host network aliases for the same interface

This commit is contained in:
Andrii Chubatiuk 2021-04-13 16:33:33 +03:00 committed by GitHub
parent 715460804a
commit d8df568f10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 70 additions and 15 deletions

View File

@ -168,10 +168,11 @@ func (f *NetworkFingerprint) createNodeNetworkResources(ifaces []net.Interface,
} else { } else {
family = structs.NodeNetworkAF_IPv6 family = structs.NodeNetworkAF_IPv6
} }
for _, alias := range deriveAddressAliases(iface, ip, conf) {
newAddr := structs.NodeNetworkAddress{ newAddr := structs.NodeNetworkAddress{
Address: ip.String(), Address: ip.String(),
Family: family, Family: family,
Alias: deriveAddressAlias(iface, ip, conf), Alias: alias,
} }
if newAddr.Alias != "" { if newAddr.Alias != "" {
@ -182,6 +183,7 @@ func (f *NetworkFingerprint) createNodeNetworkResources(ifaces []net.Interface,
} }
} }
} }
}
if len(networkAddrs) == 0 && len(linkLocalAddrs) > 0 { if len(networkAddrs) == 0 && len(linkLocalAddrs) > 0 {
if disallowLinkLocal { if disallowLinkLocal {
@ -200,7 +202,7 @@ func (f *NetworkFingerprint) createNodeNetworkResources(ifaces []net.Interface,
return nets, nil return nets, nil
} }
func deriveAddressAlias(iface net.Interface, addr net.IP, config *config.Config) string { func deriveAddressAliases(iface net.Interface, addr net.IP, config *config.Config) (aliases []string) {
for name, conf := range config.HostNetworks { for name, conf := range config.HostNetworks {
var cidrMatch, ifaceMatch bool var cidrMatch, ifaceMatch bool
if conf.CIDR != "" { if conf.CIDR != "" {
@ -231,22 +233,26 @@ func deriveAddressAlias(iface net.Interface, addr net.IP, config *config.Config)
ifaceMatch = true ifaceMatch = true
} }
if cidrMatch && ifaceMatch { if cidrMatch && ifaceMatch {
return name aliases = append(aliases, name)
} }
} }
if len(aliases) > 0 {
return
}
if config.NetworkInterface != "" { if config.NetworkInterface != "" {
if config.NetworkInterface == iface.Name { if config.NetworkInterface == iface.Name {
return "default" return []string{"default"}
} }
} else if ri, err := sockaddr.NewRouteInfo(); err == nil { } else if ri, err := sockaddr.NewRouteInfo(); err == nil {
defaultIface, err := ri.GetDefaultInterfaceName() defaultIface, err := ri.GetDefaultInterfaceName()
if err == nil && iface.Name == defaultIface { if err == nil && iface.Name == defaultIface {
return "default" return []string{"default"}
} }
} }
return "" return
} }
// createNetworkResources creates network resources for every IP // createNetworkResources creates network resources for every IP

View File

@ -4,11 +4,13 @@ import (
"fmt" "fmt"
"net" "net"
"os" "os"
"sort"
"testing" "testing"
"github.com/hashicorp/nomad/client/config" "github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/helper/testlog" "github.com/hashicorp/nomad/helper/testlog"
"github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs"
"github.com/stretchr/testify/require"
) )
// Set skipOnlineTestEnvVar to a non-empty value to skip network tests. Useful // Set skipOnlineTestEnvVar to a non-empty value to skip network tests. Useful
@ -437,3 +439,50 @@ func TestNetworkFingerPrint_LinkLocal_Disallowed(t *testing.T) {
t.Fatalf("should not apply attributes") t.Fatalf("should not apply attributes")
} }
} }
func TestNetworkFingerPrint_MultipleAliases(t *testing.T) {
f := &NetworkFingerprint{logger: testlog.HCLogger(t), interfaceDetector: &NetworkInterfaceDetectorMultipleInterfaces{}}
node := &structs.Node{
Attributes: make(map[string]string),
}
cfg := &config.Config{
NetworkSpeed: 100,
NetworkInterface: "eth3",
HostNetworks: map[string]*structs.ClientHostNetworkConfig{
"alias1": {
Name: "alias1",
Interface: "eth3",
CIDR: "169.254.155.20/32",
},
"alias2": {
Name: "alias2",
Interface: "eth3",
CIDR: "169.254.155.20/32",
},
"alias3": {
Name: "alias3",
Interface: "eth0",
CIDR: "100.64.0.11/10",
},
},
}
request := &FingerprintRequest{Config: cfg, Node: node}
var response FingerprintResponse
err := f.Fingerprint(request, &response)
require.NoError(t, err)
aliases := []string{}
for _, network := range response.NodeResources.NodeNetworks {
for _, address := range network.Addresses {
aliases = append(aliases, address.Alias)
}
}
expected := []string{}
for alias, _ := range cfg.HostNetworks {
expected = append(expected, alias)
}
sort.Strings(expected)
sort.Strings(aliases)
require.Equal(t, expected, aliases, "host networks should match aliases")
}