github.com/quite/nomad@v0.8.6/nomad/structs/network_test.go (about)

     1  package structs
     2  
     3  import (
     4  	"net"
     5  	"reflect"
     6  	"testing"
     7  )
     8  
     9  func TestNetworkIndex_Overcommitted(t *testing.T) {
    10  	idx := NewNetworkIndex()
    11  
    12  	// Consume some network
    13  	reserved := &NetworkResource{
    14  		Device:        "eth0",
    15  		IP:            "192.168.0.100",
    16  		MBits:         505,
    17  		ReservedPorts: []Port{{"one", 8000}, {"two", 9000}},
    18  	}
    19  	collide := idx.AddReserved(reserved)
    20  	if collide {
    21  		t.Fatalf("bad")
    22  	}
    23  	if !idx.Overcommitted() {
    24  		t.Fatalf("have no resources")
    25  	}
    26  
    27  	// Add resources
    28  	n := &Node{
    29  		Resources: &Resources{
    30  			Networks: []*NetworkResource{
    31  				{
    32  					Device: "eth0",
    33  					CIDR:   "192.168.0.100/32",
    34  					MBits:  1000,
    35  				},
    36  			},
    37  		},
    38  	}
    39  	idx.SetNode(n)
    40  	if idx.Overcommitted() {
    41  		t.Fatalf("have resources")
    42  	}
    43  
    44  	// Double up our usage
    45  	idx.AddReserved(reserved)
    46  	if !idx.Overcommitted() {
    47  		t.Fatalf("should be overcommitted")
    48  	}
    49  }
    50  
    51  func TestNetworkIndex_SetNode(t *testing.T) {
    52  	idx := NewNetworkIndex()
    53  	n := &Node{
    54  		Resources: &Resources{
    55  			Networks: []*NetworkResource{
    56  				{
    57  					Device: "eth0",
    58  					CIDR:   "192.168.0.100/32",
    59  					MBits:  1000,
    60  				},
    61  			},
    62  		},
    63  		Reserved: &Resources{
    64  			Networks: []*NetworkResource{
    65  				{
    66  					Device:        "eth0",
    67  					IP:            "192.168.0.100",
    68  					ReservedPorts: []Port{{"ssh", 22}},
    69  					MBits:         1,
    70  				},
    71  			},
    72  		},
    73  	}
    74  	collide := idx.SetNode(n)
    75  	if collide {
    76  		t.Fatalf("bad")
    77  	}
    78  
    79  	if len(idx.AvailNetworks) != 1 {
    80  		t.Fatalf("Bad")
    81  	}
    82  	if idx.AvailBandwidth["eth0"] != 1000 {
    83  		t.Fatalf("Bad")
    84  	}
    85  	if idx.UsedBandwidth["eth0"] != 1 {
    86  		t.Fatalf("Bad")
    87  	}
    88  	if !idx.UsedPorts["192.168.0.100"].Check(22) {
    89  		t.Fatalf("Bad")
    90  	}
    91  }
    92  
    93  func TestNetworkIndex_AddAllocs(t *testing.T) {
    94  	idx := NewNetworkIndex()
    95  	allocs := []*Allocation{
    96  		{
    97  			TaskResources: map[string]*Resources{
    98  				"web": {
    99  					Networks: []*NetworkResource{
   100  						{
   101  							Device:        "eth0",
   102  							IP:            "192.168.0.100",
   103  							MBits:         20,
   104  							ReservedPorts: []Port{{"one", 8000}, {"two", 9000}},
   105  						},
   106  					},
   107  				},
   108  			},
   109  		},
   110  		{
   111  			TaskResources: map[string]*Resources{
   112  				"api": {
   113  					Networks: []*NetworkResource{
   114  						{
   115  							Device:        "eth0",
   116  							IP:            "192.168.0.100",
   117  							MBits:         50,
   118  							ReservedPorts: []Port{{"one", 10000}},
   119  						},
   120  					},
   121  				},
   122  			},
   123  		},
   124  	}
   125  	collide := idx.AddAllocs(allocs)
   126  	if collide {
   127  		t.Fatalf("bad")
   128  	}
   129  
   130  	if idx.UsedBandwidth["eth0"] != 70 {
   131  		t.Fatalf("Bad")
   132  	}
   133  	if !idx.UsedPorts["192.168.0.100"].Check(8000) {
   134  		t.Fatalf("Bad")
   135  	}
   136  	if !idx.UsedPorts["192.168.0.100"].Check(9000) {
   137  		t.Fatalf("Bad")
   138  	}
   139  	if !idx.UsedPorts["192.168.0.100"].Check(10000) {
   140  		t.Fatalf("Bad")
   141  	}
   142  }
   143  
   144  func TestNetworkIndex_AddReserved(t *testing.T) {
   145  	idx := NewNetworkIndex()
   146  
   147  	reserved := &NetworkResource{
   148  		Device:        "eth0",
   149  		IP:            "192.168.0.100",
   150  		MBits:         20,
   151  		ReservedPorts: []Port{{"one", 8000}, {"two", 9000}},
   152  	}
   153  	collide := idx.AddReserved(reserved)
   154  	if collide {
   155  		t.Fatalf("bad")
   156  	}
   157  
   158  	if idx.UsedBandwidth["eth0"] != 20 {
   159  		t.Fatalf("Bad")
   160  	}
   161  	if !idx.UsedPorts["192.168.0.100"].Check(8000) {
   162  		t.Fatalf("Bad")
   163  	}
   164  	if !idx.UsedPorts["192.168.0.100"].Check(9000) {
   165  		t.Fatalf("Bad")
   166  	}
   167  
   168  	// Try to reserve the same network
   169  	collide = idx.AddReserved(reserved)
   170  	if !collide {
   171  		t.Fatalf("bad")
   172  	}
   173  }
   174  
   175  func TestNetworkIndex_yieldIP(t *testing.T) {
   176  	idx := NewNetworkIndex()
   177  	n := &Node{
   178  		Resources: &Resources{
   179  			Networks: []*NetworkResource{
   180  				{
   181  					Device: "eth0",
   182  					CIDR:   "192.168.0.100/30",
   183  					MBits:  1000,
   184  				},
   185  			},
   186  		},
   187  		Reserved: &Resources{
   188  			Networks: []*NetworkResource{
   189  				{
   190  					Device:        "eth0",
   191  					IP:            "192.168.0.100",
   192  					ReservedPorts: []Port{{"ssh", 22}},
   193  					MBits:         1,
   194  				},
   195  			},
   196  		},
   197  	}
   198  	idx.SetNode(n)
   199  
   200  	var out []string
   201  	idx.yieldIP(func(n *NetworkResource, ip net.IP) (stop bool) {
   202  		out = append(out, ip.String())
   203  		return
   204  	})
   205  
   206  	expect := []string{"192.168.0.100", "192.168.0.101",
   207  		"192.168.0.102", "192.168.0.103"}
   208  	if !reflect.DeepEqual(out, expect) {
   209  		t.Fatalf("bad: %v", out)
   210  	}
   211  }
   212  
   213  func TestNetworkIndex_AssignNetwork(t *testing.T) {
   214  	idx := NewNetworkIndex()
   215  	n := &Node{
   216  		Resources: &Resources{
   217  			Networks: []*NetworkResource{
   218  				{
   219  					Device: "eth0",
   220  					CIDR:   "192.168.0.100/30",
   221  					MBits:  1000,
   222  				},
   223  			},
   224  		},
   225  		Reserved: &Resources{
   226  			Networks: []*NetworkResource{
   227  				{
   228  					Device:        "eth0",
   229  					IP:            "192.168.0.100",
   230  					ReservedPorts: []Port{{"ssh", 22}},
   231  					MBits:         1,
   232  				},
   233  			},
   234  		},
   235  	}
   236  	idx.SetNode(n)
   237  
   238  	allocs := []*Allocation{
   239  		{
   240  			TaskResources: map[string]*Resources{
   241  				"web": {
   242  					Networks: []*NetworkResource{
   243  						{
   244  							Device:        "eth0",
   245  							IP:            "192.168.0.100",
   246  							MBits:         20,
   247  							ReservedPorts: []Port{{"one", 8000}, {"two", 9000}},
   248  						},
   249  					},
   250  				},
   251  			},
   252  		},
   253  		{
   254  			TaskResources: map[string]*Resources{
   255  				"api": {
   256  					Networks: []*NetworkResource{
   257  						{
   258  							Device:        "eth0",
   259  							IP:            "192.168.0.100",
   260  							MBits:         50,
   261  							ReservedPorts: []Port{{"main", 10000}},
   262  						},
   263  					},
   264  				},
   265  			},
   266  		},
   267  	}
   268  	idx.AddAllocs(allocs)
   269  
   270  	// Ask for a reserved port
   271  	ask := &NetworkResource{
   272  		ReservedPorts: []Port{{"main", 8000}},
   273  	}
   274  	offer, err := idx.AssignNetwork(ask)
   275  	if err != nil {
   276  		t.Fatalf("err: %v", err)
   277  	}
   278  	if offer == nil {
   279  		t.Fatalf("bad")
   280  	}
   281  	if offer.IP != "192.168.0.101" {
   282  		t.Fatalf("bad: %#v", offer)
   283  	}
   284  	rp := Port{"main", 8000}
   285  	if len(offer.ReservedPorts) != 1 || offer.ReservedPorts[0] != rp {
   286  		t.Fatalf("bad: %#v", offer)
   287  	}
   288  
   289  	// Ask for dynamic ports
   290  	ask = &NetworkResource{
   291  		DynamicPorts: []Port{{"http", 0}, {"https", 0}, {"admin", 0}},
   292  	}
   293  	offer, err = idx.AssignNetwork(ask)
   294  	if err != nil {
   295  		t.Fatalf("err: %v", err)
   296  	}
   297  	if offer == nil {
   298  		t.Fatalf("bad")
   299  	}
   300  	if offer.IP != "192.168.0.100" {
   301  		t.Fatalf("bad: %#v", offer)
   302  	}
   303  	if len(offer.DynamicPorts) != 3 {
   304  		t.Fatalf("There should be three dynamic ports")
   305  	}
   306  	for _, port := range offer.DynamicPorts {
   307  		if port.Value == 0 {
   308  			t.Fatalf("Dynamic Port: %v should have been assigned a host port", port.Label)
   309  		}
   310  	}
   311  
   312  	// Ask for reserved + dynamic ports
   313  	ask = &NetworkResource{
   314  		ReservedPorts: []Port{{"main", 2345}},
   315  		DynamicPorts:  []Port{{"http", 0}, {"https", 0}, {"admin", 0}},
   316  	}
   317  	offer, err = idx.AssignNetwork(ask)
   318  	if err != nil {
   319  		t.Fatalf("err: %v", err)
   320  	}
   321  	if offer == nil {
   322  		t.Fatalf("bad")
   323  	}
   324  	if offer.IP != "192.168.0.100" {
   325  		t.Fatalf("bad: %#v", offer)
   326  	}
   327  
   328  	rp = Port{"main", 2345}
   329  	if len(offer.ReservedPorts) != 1 || offer.ReservedPorts[0] != rp {
   330  		t.Fatalf("bad: %#v", offer)
   331  	}
   332  
   333  	// Ask for too much bandwidth
   334  	ask = &NetworkResource{
   335  		MBits: 1000,
   336  	}
   337  	offer, err = idx.AssignNetwork(ask)
   338  	if err.Error() != "bandwidth exceeded" {
   339  		t.Fatalf("err: %v", err)
   340  	}
   341  	if offer != nil {
   342  		t.Fatalf("bad")
   343  	}
   344  }
   345  
   346  // This test ensures that even with a small domain of available ports we are
   347  // able to make a dynamic port allocation.
   348  func TestNetworkIndex_AssignNetwork_Dynamic_Contention(t *testing.T) {
   349  
   350  	// Create a node that only has one free port
   351  	idx := NewNetworkIndex()
   352  	n := &Node{
   353  		Resources: &Resources{
   354  			Networks: []*NetworkResource{
   355  				{
   356  					Device: "eth0",
   357  					CIDR:   "192.168.0.100/32",
   358  					MBits:  1000,
   359  				},
   360  			},
   361  		},
   362  		Reserved: &Resources{
   363  			Networks: []*NetworkResource{
   364  				{
   365  					Device: "eth0",
   366  					IP:     "192.168.0.100",
   367  					MBits:  1,
   368  				},
   369  			},
   370  		},
   371  	}
   372  	for i := MinDynamicPort; i < MaxDynamicPort; i++ {
   373  		n.Reserved.Networks[0].ReservedPorts = append(n.Reserved.Networks[0].ReservedPorts, Port{Value: i})
   374  	}
   375  
   376  	idx.SetNode(n)
   377  
   378  	// Ask for dynamic ports
   379  	ask := &NetworkResource{
   380  		DynamicPorts: []Port{{"http", 0}},
   381  	}
   382  	offer, err := idx.AssignNetwork(ask)
   383  	if err != nil {
   384  		t.Fatalf("err: %v", err)
   385  	}
   386  	if offer == nil {
   387  		t.Fatalf("bad")
   388  	}
   389  	if offer.IP != "192.168.0.100" {
   390  		t.Fatalf("bad: %#v", offer)
   391  	}
   392  	if len(offer.DynamicPorts) != 1 {
   393  		t.Fatalf("There should be three dynamic ports")
   394  	}
   395  	if p := offer.DynamicPorts[0].Value; p != MaxDynamicPort {
   396  		t.Fatalf("Dynamic Port: should have been assigned %d; got %d", p, MaxDynamicPort)
   397  	}
   398  }
   399  
   400  func TestIntContains(t *testing.T) {
   401  	l := []int{1, 2, 10, 20}
   402  	if isPortReserved(l, 50) {
   403  		t.Fatalf("bad")
   404  	}
   405  	if !isPortReserved(l, 20) {
   406  		t.Fatalf("bad")
   407  	}
   408  	if !isPortReserved(l, 1) {
   409  		t.Fatalf("bad")
   410  	}
   411  }