From bab0d39d51666142548ec1dc09f1428008c1d4d4 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Tue, 13 Apr 2021 16:33:33 +0300 Subject: [PATCH] support multiple host network aliases for the same interface --- client/fingerprint/network.go | 36 +++++++++++++--------- client/fingerprint/network_test.go | 49 ++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 15 deletions(-) diff --git a/client/fingerprint/network.go b/client/fingerprint/network.go index 1c77a7657b3..b36a5482684 100644 --- a/client/fingerprint/network.go +++ b/client/fingerprint/network.go @@ -168,17 +168,19 @@ func (f *NetworkFingerprint) createNodeNetworkResources(ifaces []net.Interface, } else { family = structs.NodeNetworkAF_IPv6 } - newAddr := structs.NodeNetworkAddress{ - Address: ip.String(), - Family: family, - Alias: deriveAddressAlias(iface, ip, conf), - } + for _, alias := range deriveAddressAliases(iface, ip, conf) { + newAddr := structs.NodeNetworkAddress{ + Address: ip.String(), + Family: family, + Alias: alias, + } - if newAddr.Alias != "" { - if ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() { - linkLocalAddrs = append(linkLocalAddrs, newAddr) - } else { - networkAddrs = append(networkAddrs, newAddr) + if newAddr.Alias != "" { + if ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() { + linkLocalAddrs = append(linkLocalAddrs, newAddr) + } else { + networkAddrs = append(networkAddrs, newAddr) + } } } } @@ -200,7 +202,7 @@ func (f *NetworkFingerprint) createNodeNetworkResources(ifaces []net.Interface, 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 { var cidrMatch, ifaceMatch bool if conf.CIDR != "" { @@ -231,22 +233,26 @@ func deriveAddressAlias(iface net.Interface, addr net.IP, config *config.Config) ifaceMatch = true } if cidrMatch && ifaceMatch { - return name + aliases = append(aliases, name) } } + if len(aliases) > 0 { + return + } + if config.NetworkInterface != "" { if config.NetworkInterface == iface.Name { - return "default" + return []string{"default"} } } else if ri, err := sockaddr.NewRouteInfo(); err == nil { defaultIface, err := ri.GetDefaultInterfaceName() if err == nil && iface.Name == defaultIface { - return "default" + return []string{"default"} } } - return "" + return } // createNetworkResources creates network resources for every IP diff --git a/client/fingerprint/network_test.go b/client/fingerprint/network_test.go index 5b55b87a690..4b0fce93dcc 100644 --- a/client/fingerprint/network_test.go +++ b/client/fingerprint/network_test.go @@ -4,11 +4,13 @@ import ( "fmt" "net" "os" + "sort" "testing" "github.com/hashicorp/nomad/client/config" "github.com/hashicorp/nomad/helper/testlog" "github.com/hashicorp/nomad/nomad/structs" + "github.com/stretchr/testify/require" ) // 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") } } + +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") +}