github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/client/serviceregistration/address_test.go (about)

     1  package serviceregistration
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/hashicorp/nomad/nomad/structs"
     7  	"github.com/hashicorp/nomad/plugins/drivers"
     8  	"github.com/stretchr/testify/require"
     9  )
    10  
    11  func Test_GetAddress(t *testing.T) {
    12  	const HostIP = "127.0.0.1"
    13  
    14  	testCases := []struct {
    15  		name string
    16  
    17  		// Inputs
    18  		advertise string
    19  		mode      string
    20  		portLabel string
    21  		host      map[string]int // will be converted to structs.Networks
    22  		driver    *drivers.DriverNetwork
    23  		ports     structs.AllocatedPorts
    24  		status    *structs.AllocNetworkStatus
    25  
    26  		// Expectations
    27  		expIP   string
    28  		expPort int
    29  		expErr  string
    30  	}{
    31  		// Valid Configurations
    32  		{
    33  			name:      "ExampleService",
    34  			mode:      structs.AddressModeAuto,
    35  			portLabel: "db",
    36  			host:      map[string]int{"db": 12435},
    37  			driver: &drivers.DriverNetwork{
    38  				PortMap: map[string]int{"db": 6379},
    39  				IP:      "10.1.2.3",
    40  			},
    41  			expIP:   HostIP,
    42  			expPort: 12435,
    43  		},
    44  		{
    45  			name:      "host",
    46  			mode:      structs.AddressModeHost,
    47  			portLabel: "db",
    48  			host:      map[string]int{"db": 12345},
    49  			driver: &drivers.DriverNetwork{
    50  				PortMap: map[string]int{"db": 6379},
    51  				IP:      "10.1.2.3",
    52  			},
    53  			expIP:   HostIP,
    54  			expPort: 12345,
    55  		},
    56  		{
    57  			name:      "driver",
    58  			mode:      structs.AddressModeDriver,
    59  			portLabel: "db",
    60  			host:      map[string]int{"db": 12345},
    61  			driver: &drivers.DriverNetwork{
    62  				PortMap: map[string]int{"db": 6379},
    63  				IP:      "10.1.2.3",
    64  			},
    65  			expIP:   "10.1.2.3",
    66  			expPort: 6379,
    67  		},
    68  		{
    69  			name:      "AutoDriver",
    70  			mode:      structs.AddressModeAuto,
    71  			portLabel: "db",
    72  			host:      map[string]int{"db": 12345},
    73  			driver: &drivers.DriverNetwork{
    74  				PortMap:       map[string]int{"db": 6379},
    75  				IP:            "10.1.2.3",
    76  				AutoAdvertise: true,
    77  			},
    78  			expIP:   "10.1.2.3",
    79  			expPort: 6379,
    80  		},
    81  		{
    82  			name:      "DriverCustomPort",
    83  			mode:      structs.AddressModeDriver,
    84  			portLabel: "7890",
    85  			host:      map[string]int{"db": 12345},
    86  			driver: &drivers.DriverNetwork{
    87  				PortMap: map[string]int{"db": 6379},
    88  				IP:      "10.1.2.3",
    89  			},
    90  			expIP:   "10.1.2.3",
    91  			expPort: 7890,
    92  		},
    93  
    94  		// Invalid Configurations
    95  		{
    96  			name:      "DriverWithoutNetwork",
    97  			mode:      structs.AddressModeDriver,
    98  			portLabel: "db",
    99  			host:      map[string]int{"db": 12345},
   100  			driver:    nil,
   101  			expErr:    "no driver network exists",
   102  		},
   103  		{
   104  			name:      "DriverBadPort",
   105  			mode:      structs.AddressModeDriver,
   106  			portLabel: "bad-port-label",
   107  			host:      map[string]int{"db": 12345},
   108  			driver: &drivers.DriverNetwork{
   109  				PortMap: map[string]int{"db": 6379},
   110  				IP:      "10.1.2.3",
   111  			},
   112  			expErr: "invalid port",
   113  		},
   114  		{
   115  			name:      "DriverZeroPort",
   116  			mode:      structs.AddressModeDriver,
   117  			portLabel: "0",
   118  			driver: &drivers.DriverNetwork{
   119  				IP: "10.1.2.3",
   120  			},
   121  			expErr: "invalid port",
   122  		},
   123  		{
   124  			name:      "HostBadPort",
   125  			mode:      structs.AddressModeHost,
   126  			portLabel: "bad-port-label",
   127  			expErr:    "invalid port",
   128  		},
   129  		{
   130  			name:      "InvalidMode",
   131  			mode:      "invalid-mode",
   132  			portLabel: "80",
   133  			expErr:    "invalid address mode",
   134  		},
   135  		{
   136  			name:  "NoPort_AutoMode",
   137  			mode:  structs.AddressModeAuto,
   138  			expIP: HostIP,
   139  		},
   140  		{
   141  			name:  "NoPort_HostMode",
   142  			mode:  structs.AddressModeHost,
   143  			expIP: HostIP,
   144  		},
   145  		{
   146  			name: "NoPort_DriverMode",
   147  			mode: structs.AddressModeDriver,
   148  			driver: &drivers.DriverNetwork{
   149  				IP: "10.1.2.3",
   150  			},
   151  			expIP: "10.1.2.3",
   152  		},
   153  
   154  		// Scenarios using port 0.12 networking fields (NetworkStatus, AllocatedPortMapping)
   155  		{
   156  			name:      "ExampleServer_withAllocatedPorts",
   157  			mode:      structs.AddressModeAuto,
   158  			portLabel: "db",
   159  			ports: []structs.AllocatedPortMapping{
   160  				{
   161  					Label:  "db",
   162  					Value:  12435,
   163  					To:     6379,
   164  					HostIP: HostIP,
   165  				},
   166  			},
   167  			status: &structs.AllocNetworkStatus{
   168  				InterfaceName: "eth0",
   169  				Address:       "172.26.0.1",
   170  			},
   171  			expIP:   HostIP,
   172  			expPort: 12435,
   173  		},
   174  		{
   175  			name:      "Host_withAllocatedPorts",
   176  			mode:      structs.AddressModeHost,
   177  			portLabel: "db",
   178  			ports: []structs.AllocatedPortMapping{
   179  				{
   180  					Label:  "db",
   181  					Value:  12345,
   182  					To:     6379,
   183  					HostIP: HostIP,
   184  				},
   185  			},
   186  			status: &structs.AllocNetworkStatus{
   187  				InterfaceName: "eth0",
   188  				Address:       "172.26.0.1",
   189  			},
   190  			expIP:   HostIP,
   191  			expPort: 12345,
   192  		},
   193  		{
   194  			name:      "Driver_withAllocatedPorts",
   195  			mode:      structs.AddressModeDriver,
   196  			portLabel: "db",
   197  			ports: []structs.AllocatedPortMapping{
   198  				{
   199  					Label:  "db",
   200  					Value:  12345,
   201  					To:     6379,
   202  					HostIP: HostIP,
   203  				},
   204  			},
   205  			driver: &drivers.DriverNetwork{
   206  				IP: "10.1.2.3",
   207  			},
   208  			status: &structs.AllocNetworkStatus{
   209  				InterfaceName: "eth0",
   210  				Address:       "172.26.0.1",
   211  			},
   212  			expIP:   "10.1.2.3",
   213  			expPort: 6379,
   214  		},
   215  		{
   216  			name:      "AutoDriver_withAllocatedPorts",
   217  			mode:      structs.AddressModeAuto,
   218  			portLabel: "db",
   219  			ports: []structs.AllocatedPortMapping{
   220  				{
   221  					Label:  "db",
   222  					Value:  12345,
   223  					To:     6379,
   224  					HostIP: HostIP,
   225  				},
   226  			},
   227  			driver: &drivers.DriverNetwork{
   228  				IP:            "10.1.2.3",
   229  				AutoAdvertise: true,
   230  			},
   231  			status: &structs.AllocNetworkStatus{
   232  				InterfaceName: "eth0",
   233  				Address:       "172.26.0.1",
   234  			},
   235  			expIP:   "10.1.2.3",
   236  			expPort: 6379,
   237  		},
   238  		{
   239  			name:      "DriverCustomPort_withAllocatedPorts",
   240  			mode:      structs.AddressModeDriver,
   241  			portLabel: "7890",
   242  			ports: []structs.AllocatedPortMapping{
   243  				{
   244  					Label:  "db",
   245  					Value:  12345,
   246  					To:     6379,
   247  					HostIP: HostIP,
   248  				},
   249  			},
   250  			driver: &drivers.DriverNetwork{
   251  				IP: "10.1.2.3",
   252  			},
   253  			status: &structs.AllocNetworkStatus{
   254  				InterfaceName: "eth0",
   255  				Address:       "172.26.0.1",
   256  			},
   257  			expIP:   "10.1.2.3",
   258  			expPort: 7890,
   259  		},
   260  		{
   261  			name:      "Host_MultiHostInterface",
   262  			mode:      structs.AddressModeAuto,
   263  			portLabel: "db",
   264  			ports: []structs.AllocatedPortMapping{
   265  				{
   266  					Label:  "db",
   267  					Value:  12345,
   268  					To:     6379,
   269  					HostIP: "127.0.0.100",
   270  				},
   271  			},
   272  			status: &structs.AllocNetworkStatus{
   273  				InterfaceName: "eth0",
   274  				Address:       "172.26.0.1",
   275  			},
   276  			expIP:   "127.0.0.100",
   277  			expPort: 12345,
   278  		},
   279  		{
   280  			name:      "Alloc",
   281  			mode:      structs.AddressModeAlloc,
   282  			portLabel: "db",
   283  			ports: []structs.AllocatedPortMapping{
   284  				{
   285  					Label:  "db",
   286  					Value:  12345,
   287  					To:     6379,
   288  					HostIP: HostIP,
   289  				},
   290  			},
   291  			status: &structs.AllocNetworkStatus{
   292  				InterfaceName: "eth0",
   293  				Address:       "172.26.0.1",
   294  			},
   295  			expIP:   "172.26.0.1",
   296  			expPort: 6379,
   297  		},
   298  		{
   299  			name:      "Alloc no to value",
   300  			mode:      structs.AddressModeAlloc,
   301  			portLabel: "db",
   302  			ports: []structs.AllocatedPortMapping{
   303  				{
   304  					Label:  "db",
   305  					Value:  12345,
   306  					HostIP: HostIP,
   307  				},
   308  			},
   309  			status: &structs.AllocNetworkStatus{
   310  				InterfaceName: "eth0",
   311  				Address:       "172.26.0.1",
   312  			},
   313  			expIP:   "172.26.0.1",
   314  			expPort: 12345,
   315  		},
   316  		{
   317  			name:      "AllocCustomPort",
   318  			mode:      structs.AddressModeAlloc,
   319  			portLabel: "6379",
   320  			status: &structs.AllocNetworkStatus{
   321  				InterfaceName: "eth0",
   322  				Address:       "172.26.0.1",
   323  			},
   324  			expIP:   "172.26.0.1",
   325  			expPort: 6379,
   326  		},
   327  		// Cases for setting the address field
   328  		{
   329  			name:      "Address",
   330  			mode:      structs.AddressModeAuto,
   331  			advertise: "example.com",
   332  			expIP:     "example.com",
   333  			expPort:   0,
   334  		},
   335  		{
   336  			name:      "Address with numeric port",
   337  			mode:      structs.AddressModeAuto,
   338  			advertise: "example.com",
   339  			portLabel: "8080",
   340  			expIP:     "example.com",
   341  			expPort:   8080,
   342  		},
   343  		{
   344  			name:      "Address with mapped port",
   345  			mode:      structs.AddressModeAuto,
   346  			portLabel: "web",
   347  			advertise: "example.com",
   348  			ports: []structs.AllocatedPortMapping{
   349  				{
   350  					Label:  "web",
   351  					Value:  12345,
   352  					HostIP: HostIP,
   353  				},
   354  			},
   355  			expIP:   "example.com",
   356  			expPort: 12345,
   357  		},
   358  		{
   359  			name:      "Address with invalid mapped port",
   360  			mode:      structs.AddressModeAuto,
   361  			advertise: "example.com",
   362  			portLabel: "foobar",
   363  			expErr:    `invalid port: "foobar": not a valid port mapping or numeric port`,
   364  		},
   365  		{
   366  			name:      "Address with host mode",
   367  			mode:      structs.AddressModeHost,
   368  			advertise: "example.com",
   369  			expErr:    `cannot use custom advertise address with "host" address mode`,
   370  		},
   371  		{
   372  			name:      "Address with driver mode",
   373  			mode:      structs.AddressModeDriver,
   374  			advertise: "example.com",
   375  			expErr:    `cannot use custom advertise address with "driver" address mode`,
   376  		},
   377  		{
   378  			name:      "Address with alloc mode",
   379  			mode:      structs.AddressModeAlloc,
   380  			advertise: "example.com",
   381  			expErr:    `cannot use custom advertise address with "alloc" address mode`,
   382  		},
   383  	}
   384  
   385  	for _, tc := range testCases {
   386  		t.Run(tc.name, func(t *testing.T) {
   387  
   388  			// Convert host port map into a structs.Networks.
   389  			networks := []*structs.NetworkResource{
   390  				{
   391  					IP:            HostIP,
   392  					ReservedPorts: make([]structs.Port, len(tc.host)),
   393  				},
   394  			}
   395  
   396  			i := 0
   397  			for label, port := range tc.host {
   398  				networks[0].ReservedPorts[i].Label = label
   399  				networks[0].ReservedPorts[i].Value = port
   400  				i++
   401  			}
   402  
   403  			// Run the GetAddress function.
   404  			actualIP, actualPort, actualErr := GetAddress(
   405  				tc.advertise,
   406  				tc.mode,
   407  				tc.portLabel,
   408  				networks,
   409  				tc.driver,
   410  				tc.ports,
   411  				tc.status,
   412  			)
   413  
   414  			// Assert the results
   415  			require.Equal(t, tc.expIP, actualIP, "IP mismatch")
   416  			require.Equal(t, tc.expPort, actualPort, "Port mismatch")
   417  			if tc.expErr == "" {
   418  				require.Nil(t, actualErr)
   419  			} else {
   420  				require.Error(t, actualErr)
   421  				require.Contains(t, actualErr.Error(), tc.expErr)
   422  			}
   423  		})
   424  	}
   425  }