github.com/mattyr/nomad@v0.3.3-0.20160919021406-3485a065154a/client/fingerprint/network_test.go (about)

     1  package fingerprint
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"os"
     7  	"testing"
     8  
     9  	"github.com/hashicorp/nomad/client/config"
    10  	"github.com/hashicorp/nomad/nomad/structs"
    11  )
    12  
    13  // Set skipOnlineTestEnvVar to a non-empty value to skip network tests.  Useful
    14  // when working offline (e.g. an airplane).
    15  const skipOnlineTestsEnvVar = "TEST_NOMAD_SKIP_ONLINE_NET"
    16  
    17  var (
    18  	lo = net.Interface{
    19  		Index:        2,
    20  		MTU:          65536,
    21  		Name:         "lo",
    22  		HardwareAddr: []byte{23, 43, 54, 54},
    23  		Flags:        net.FlagUp | net.FlagLoopback,
    24  	}
    25  
    26  	eth0 = net.Interface{
    27  		Index:        3,
    28  		MTU:          1500,
    29  		Name:         "eth0",
    30  		HardwareAddr: []byte{23, 44, 54, 67},
    31  		Flags:        net.FlagUp | net.FlagMulticast | net.FlagBroadcast,
    32  	}
    33  
    34  	eth1 = net.Interface{
    35  		Index:        4,
    36  		MTU:          1500,
    37  		Name:         "eth1",
    38  		HardwareAddr: []byte{23, 44, 54, 69},
    39  		Flags:        net.FlagMulticast | net.FlagBroadcast,
    40  	}
    41  
    42  	eth2 = net.Interface{
    43  		Index:        4,
    44  		MTU:          1500,
    45  		Name:         "eth2",
    46  		HardwareAddr: []byte{23, 44, 54, 70},
    47  		Flags:        net.FlagUp | net.FlagBroadcast | net.FlagMulticast,
    48  	}
    49  )
    50  
    51  // A fake network detector which returns no devices
    52  type NetworkIntefaceDetectorNoDevices struct {
    53  }
    54  
    55  func (f *NetworkIntefaceDetectorNoDevices) Interfaces() ([]net.Interface, error) {
    56  	return make([]net.Interface, 0), nil
    57  }
    58  
    59  func (f *NetworkIntefaceDetectorNoDevices) InterfaceByName(name string) (*net.Interface, error) {
    60  	return nil, fmt.Errorf("Device with name %s doesn't exist", name)
    61  }
    62  
    63  func (f *NetworkIntefaceDetectorNoDevices) Addrs(intf *net.Interface) ([]net.Addr, error) {
    64  	return nil, fmt.Errorf("No interfaces found for device %v", intf.Name)
    65  }
    66  
    67  // A fake network detector which returns only loopback
    68  type NetworkInterfaceDetectorOnlyLo struct {
    69  }
    70  
    71  func (n *NetworkInterfaceDetectorOnlyLo) Interfaces() ([]net.Interface, error) {
    72  	return []net.Interface{lo}, nil
    73  }
    74  
    75  func (n *NetworkInterfaceDetectorOnlyLo) InterfaceByName(name string) (*net.Interface, error) {
    76  	if name == "lo" {
    77  		return &lo, nil
    78  	}
    79  
    80  	return nil, fmt.Errorf("No device with name %v found", name)
    81  }
    82  
    83  func (n *NetworkInterfaceDetectorOnlyLo) Addrs(intf *net.Interface) ([]net.Addr, error) {
    84  	if intf.Name == "lo" {
    85  		_, ipnet1, _ := net.ParseCIDR("127.0.0.1/8")
    86  		_, ipnet2, _ := net.ParseCIDR("2001:DB8::/48")
    87  		return []net.Addr{ipnet1, ipnet2}, nil
    88  	}
    89  
    90  	return nil, fmt.Errorf("Can't find addresses for device: %v", intf.Name)
    91  }
    92  
    93  // A fake network detector which simulates the presence of multiple interfaces
    94  type NetworkInterfaceDetectorMultipleInterfaces struct {
    95  }
    96  
    97  func (n *NetworkInterfaceDetectorMultipleInterfaces) Interfaces() ([]net.Interface, error) {
    98  	return []net.Interface{lo, eth0, eth1, eth2}, nil
    99  }
   100  
   101  func (n *NetworkInterfaceDetectorMultipleInterfaces) InterfaceByName(name string) (*net.Interface, error) {
   102  	var intf *net.Interface
   103  	switch name {
   104  	case "lo":
   105  		intf = &lo
   106  	case "eth0":
   107  		intf = &eth0
   108  	case "eth1":
   109  		intf = &eth1
   110  	case "eth2":
   111  		intf = &eth2
   112  	}
   113  	if intf != nil {
   114  		return intf, nil
   115  	}
   116  
   117  	return nil, fmt.Errorf("No device with name %v found", name)
   118  }
   119  
   120  func (n *NetworkInterfaceDetectorMultipleInterfaces) Addrs(intf *net.Interface) ([]net.Addr, error) {
   121  	if intf.Name == "lo" {
   122  		_, ipnet1, _ := net.ParseCIDR("127.0.0.1/8")
   123  		_, ipnet2, _ := net.ParseCIDR("2001:DB8::/48")
   124  		return []net.Addr{ipnet1, ipnet2}, nil
   125  	}
   126  
   127  	if intf.Name == "eth0" {
   128  		_, ipnet1, _ := net.ParseCIDR("100.64.0.11/10")
   129  		_, ipnet2, _ := net.ParseCIDR("2005:DB6::/48")
   130  		return []net.Addr{ipnet1, ipnet2}, nil
   131  	}
   132  
   133  	if intf.Name == "eth1" {
   134  		_, ipnet1, _ := net.ParseCIDR("100.64.0.10/10")
   135  		_, ipnet2, _ := net.ParseCIDR("2003:DB8::/48")
   136  		return []net.Addr{ipnet1, ipnet2}, nil
   137  	}
   138  
   139  	if intf.Name == "eth2" {
   140  		return []net.Addr{}, nil
   141  	}
   142  	return nil, fmt.Errorf("Can't find addresses for device: %v", intf.Name)
   143  }
   144  
   145  func TestNetworkFingerprint_basic(t *testing.T) {
   146  	if v := os.Getenv(skipOnlineTestsEnvVar); v != "" {
   147  		t.Skipf("Environment variable %+q not empty, skipping test", skipOnlineTestsEnvVar)
   148  	}
   149  
   150  	f := &NetworkFingerprint{logger: testLogger(), interfaceDetector: &DefaultNetworkInterfaceDetector{}}
   151  	node := &structs.Node{
   152  		Attributes: make(map[string]string),
   153  	}
   154  	cfg := &config.Config{NetworkSpeed: 100}
   155  
   156  	ok, err := f.Fingerprint(cfg, node)
   157  	if err != nil {
   158  		t.Fatalf("err: %v", err)
   159  	}
   160  	if !ok {
   161  		t.Fatalf("should apply (HINT: working offline? Set env %q=y", skipOnlineTestsEnvVar)
   162  	}
   163  
   164  	assertNodeAttributeContains(t, node, "unique.network.ip-address")
   165  
   166  	ip := node.Attributes["unique.network.ip-address"]
   167  	match := net.ParseIP(ip)
   168  	if match == nil {
   169  		t.Fatalf("Bad IP match: %s", ip)
   170  	}
   171  
   172  	if node.Resources == nil || len(node.Resources.Networks) == 0 {
   173  		t.Fatal("Expected to find Network Resources")
   174  	}
   175  
   176  	// Test at least the first Network Resource
   177  	net := node.Resources.Networks[0]
   178  	if net.IP == "" {
   179  		t.Fatal("Expected Network Resource to not be empty")
   180  	}
   181  	if net.CIDR == "" {
   182  		t.Fatal("Expected Network Resource to have a CIDR")
   183  	}
   184  	if net.Device == "" {
   185  		t.Fatal("Expected Network Resource to have a Device Name")
   186  	}
   187  	if net.MBits == 0 {
   188  		t.Fatal("Expected Network Resource to have a non-zero bandwith")
   189  	}
   190  }
   191  
   192  func TestNetworkFingerprint_no_devices(t *testing.T) {
   193  	f := &NetworkFingerprint{logger: testLogger(), interfaceDetector: &NetworkIntefaceDetectorNoDevices{}}
   194  	node := &structs.Node{
   195  		Attributes: make(map[string]string),
   196  	}
   197  	cfg := &config.Config{NetworkSpeed: 100}
   198  
   199  	ok, err := f.Fingerprint(cfg, node)
   200  	if err != nil {
   201  		t.Fatalf("err: %v", err)
   202  	}
   203  
   204  	if ok {
   205  		t.Fatalf("ok: %v", ok)
   206  	}
   207  }
   208  
   209  func TestNetworkFingerprint_default_device_absent(t *testing.T) {
   210  	f := &NetworkFingerprint{logger: testLogger(), interfaceDetector: &NetworkInterfaceDetectorOnlyLo{}}
   211  	node := &structs.Node{
   212  		Attributes: make(map[string]string),
   213  	}
   214  	cfg := &config.Config{NetworkSpeed: 100, NetworkInterface: "eth0"}
   215  
   216  	ok, err := f.Fingerprint(cfg, node)
   217  	if err == nil {
   218  		t.Fatalf("err: %v", err)
   219  	}
   220  
   221  	if ok {
   222  		t.Fatalf("ok: %v", ok)
   223  	}
   224  }
   225  
   226  func TestNetworkFingerPrint_default_device(t *testing.T) {
   227  	f := &NetworkFingerprint{logger: testLogger(), interfaceDetector: &NetworkInterfaceDetectorOnlyLo{}}
   228  	node := &structs.Node{
   229  		Attributes: make(map[string]string),
   230  	}
   231  	cfg := &config.Config{NetworkSpeed: 100, NetworkInterface: "lo"}
   232  
   233  	ok, err := f.Fingerprint(cfg, node)
   234  	if err != nil {
   235  		t.Fatalf("err: %v", err)
   236  	}
   237  	if !ok {
   238  		t.Fatalf("should apply")
   239  	}
   240  
   241  	assertNodeAttributeContains(t, node, "unique.network.ip-address")
   242  
   243  	ip := node.Attributes["unique.network.ip-address"]
   244  	match := net.ParseIP(ip)
   245  	if match == nil {
   246  		t.Fatalf("Bad IP match: %s", ip)
   247  	}
   248  
   249  	if node.Resources == nil || len(node.Resources.Networks) == 0 {
   250  		t.Fatal("Expected to find Network Resources")
   251  	}
   252  
   253  	// Test at least the first Network Resource
   254  	net := node.Resources.Networks[0]
   255  	if net.IP == "" {
   256  		t.Fatal("Expected Network Resource to not be empty")
   257  	}
   258  	if net.CIDR == "" {
   259  		t.Fatal("Expected Network Resource to have a CIDR")
   260  	}
   261  	if net.Device == "" {
   262  		t.Fatal("Expected Network Resource to have a Device Name")
   263  	}
   264  	if net.MBits == 0 {
   265  		t.Fatal("Expected Network Resource to have a non-zero bandwith")
   266  	}
   267  }
   268  
   269  func TestNetworkFingerPrint_excludelo_down_interfaces(t *testing.T) {
   270  	f := &NetworkFingerprint{logger: testLogger(), interfaceDetector: &NetworkInterfaceDetectorMultipleInterfaces{}}
   271  	node := &structs.Node{
   272  		Attributes: make(map[string]string),
   273  	}
   274  	cfg := &config.Config{NetworkSpeed: 100}
   275  
   276  	ok, err := f.Fingerprint(cfg, node)
   277  	if err != nil {
   278  		t.Fatalf("err: %v", err)
   279  	}
   280  	if !ok {
   281  		t.Fatalf("should apply")
   282  	}
   283  
   284  	assertNodeAttributeContains(t, node, "unique.network.ip-address")
   285  
   286  	ip := node.Attributes["unique.network.ip-address"]
   287  	match := net.ParseIP(ip)
   288  	if match == nil {
   289  		t.Fatalf("Bad IP match: %s", ip)
   290  	}
   291  
   292  	if node.Resources == nil || len(node.Resources.Networks) == 0 {
   293  		t.Fatal("Expected to find Network Resources")
   294  	}
   295  
   296  	// Test at least the first Network Resource
   297  	net := node.Resources.Networks[0]
   298  	if net.IP == "" {
   299  		t.Fatal("Expected Network Resource to have an IP")
   300  	}
   301  	if net.CIDR == "" {
   302  		t.Fatal("Expected Network Resource to have a CIDR")
   303  	}
   304  	if net.Device != "eth0" {
   305  		t.Fatal("Expected Network Resource to be eth0. Actual: ", net.Device)
   306  	}
   307  	if net.MBits == 0 {
   308  		t.Fatal("Expected Network Resource to have a non-zero bandwith")
   309  	}
   310  }