github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/client/serviceregistration/wrapper/wrapper_test.go (about) 1 package wrapper 2 3 import ( 4 "testing" 5 6 "github.com/hashicorp/go-hclog" 7 "github.com/hashicorp/nomad/client/serviceregistration" 8 regMock "github.com/hashicorp/nomad/client/serviceregistration/mock" 9 "github.com/hashicorp/nomad/nomad/structs" 10 "github.com/stretchr/testify/require" 11 ) 12 13 func Test_NewHandlerWrapper(t *testing.T) { 14 log := hclog.NewNullLogger() 15 mockProvider := regMock.NewServiceRegistrationHandler(log) 16 wrapper := NewHandlerWrapper(log, mockProvider, mockProvider) 17 require.NotNil(t, wrapper) 18 require.NotNil(t, wrapper.log) 19 require.NotNil(t, wrapper.nomadServiceProvider) 20 require.NotNil(t, wrapper.consulServiceProvider) 21 } 22 23 func TestHandlerWrapper_RegisterWorkload(t *testing.T) { 24 testCases := []struct { 25 testFn func(t *testing.T) 26 name string 27 }{ 28 { 29 testFn: func(t *testing.T) { 30 31 // Generate the test wrapper and provider mocks. 32 wrapper, consul, nomad := setupTestWrapper() 33 34 // Call the function with no services and check that nothing is 35 // registered. 36 require.NoError(t, wrapper.RegisterWorkload(&serviceregistration.WorkloadServices{})) 37 require.Len(t, consul.GetOps(), 0) 38 require.Len(t, nomad.GetOps(), 0) 39 }, 40 name: "zero services", 41 }, 42 { 43 testFn: func(t *testing.T) { 44 45 // Generate the test wrapper and provider mocks. 46 wrapper, consul, nomad := setupTestWrapper() 47 48 // Generate a minimal workload with an unknown provider. 49 workload := serviceregistration.WorkloadServices{ 50 Services: []*structs.Service{ 51 { 52 Provider: "istio", 53 }, 54 }, 55 } 56 57 // Call register and ensure an error is returned along with 58 // nothing registered in the providers. 59 err := wrapper.RegisterWorkload(&workload) 60 require.Error(t, err) 61 require.Contains(t, err.Error(), "unknown service registration provider: \"istio\"") 62 require.Len(t, consul.GetOps(), 0) 63 require.Len(t, nomad.GetOps(), 0) 64 65 }, 66 name: "unknown provider", 67 }, 68 { 69 testFn: func(t *testing.T) { 70 71 // Generate the test wrapper and provider mocks. 72 wrapper, consul, nomad := setupTestWrapper() 73 74 // Generate a minimal workload with the nomad provider. 75 workload := serviceregistration.WorkloadServices{ 76 Services: []*structs.Service{ 77 { 78 Provider: structs.ServiceProviderNomad, 79 }, 80 }, 81 } 82 83 // Call register and ensure no error is returned along with the 84 // correct operations. 85 require.NoError(t, wrapper.RegisterWorkload(&workload)) 86 require.Len(t, consul.GetOps(), 0) 87 require.Len(t, nomad.GetOps(), 1) 88 89 }, 90 name: "nomad provider", 91 }, 92 { 93 testFn: func(t *testing.T) { 94 95 // Generate the test wrapper and provider mocks. 96 wrapper, consul, nomad := setupTestWrapper() 97 98 // Generate a minimal workload with the consul provider. 99 workload := serviceregistration.WorkloadServices{ 100 Services: []*structs.Service{ 101 { 102 Provider: structs.ServiceProviderConsul, 103 }, 104 }, 105 } 106 107 // Call register and ensure no error is returned along with the 108 // correct operations. 109 require.NoError(t, wrapper.RegisterWorkload(&workload)) 110 require.Len(t, consul.GetOps(), 1) 111 require.Len(t, nomad.GetOps(), 0) 112 }, 113 name: "consul provider", 114 }, 115 } 116 117 for _, tc := range testCases { 118 t.Run(tc.name, func(t *testing.T) { 119 tc.testFn(t) 120 }) 121 } 122 } 123 124 func TestHandlerWrapper_RemoveWorkload(t *testing.T) { 125 testCases := []struct { 126 testFn func(t *testing.T) 127 name string 128 }{ 129 { 130 testFn: func(t *testing.T) { 131 // Generate the test wrapper and provider mocks. 132 wrapper, consul, nomad := setupTestWrapper() 133 134 // Call the function with no services and check that consul is 135 // defaulted to. 136 wrapper.RemoveWorkload(&serviceregistration.WorkloadServices{}) 137 require.Len(t, consul.GetOps(), 1) 138 require.Len(t, nomad.GetOps(), 0) 139 }, 140 name: "zero services", 141 }, 142 { 143 testFn: func(t *testing.T) { 144 145 // Generate the test wrapper and provider mocks. 146 wrapper, consul, nomad := setupTestWrapper() 147 148 // Generate a minimal workload with an unknown provider. 149 workload := serviceregistration.WorkloadServices{ 150 Services: []*structs.Service{ 151 { 152 Provider: "istio", 153 }, 154 }, 155 } 156 157 // Call remove and ensure nothing registered in the providers. 158 wrapper.RemoveWorkload(&workload) 159 require.Len(t, consul.GetOps(), 0) 160 require.Len(t, nomad.GetOps(), 0) 161 }, 162 name: "unknown provider", 163 }, 164 { 165 testFn: func(t *testing.T) { 166 167 // Generate the test wrapper and provider mocks. 168 wrapper, consul, nomad := setupTestWrapper() 169 170 // Generate a minimal workload with the consul provider. 171 workload := serviceregistration.WorkloadServices{ 172 Services: []*structs.Service{ 173 { 174 Provider: structs.ServiceProviderConsul, 175 }, 176 }, 177 } 178 179 // Call remove and ensure the correct backend includes 180 // operations. 181 wrapper.RemoveWorkload(&workload) 182 require.Len(t, consul.GetOps(), 1) 183 require.Len(t, nomad.GetOps(), 0) 184 }, 185 name: "consul provider", 186 }, 187 { 188 testFn: func(t *testing.T) { 189 190 // Generate the test wrapper and provider mocks. 191 wrapper, consul, nomad := setupTestWrapper() 192 193 // Generate a minimal workload with the nomad provider. 194 workload := serviceregistration.WorkloadServices{ 195 Services: []*structs.Service{ 196 { 197 Provider: structs.ServiceProviderNomad, 198 }, 199 }, 200 } 201 202 // Call remove and ensure the correct backend includes 203 // operations. 204 wrapper.RemoveWorkload(&workload) 205 require.Len(t, consul.GetOps(), 0) 206 require.Len(t, nomad.GetOps(), 1) 207 }, 208 name: "nomad provider", 209 }, 210 } 211 212 for _, tc := range testCases { 213 t.Run(tc.name, func(t *testing.T) { 214 tc.testFn(t) 215 }) 216 } 217 } 218 219 func TestHandlerWrapper_UpdateWorkload(t *testing.T) { 220 testCases := []struct { 221 testFn func(t *testing.T) 222 name string 223 }{ 224 { 225 testFn: func(t *testing.T) { 226 227 // Generate the test wrapper and provider mocks. 228 wrapper, consul, nomad := setupTestWrapper() 229 230 // Call the function with no services and check that nothing is 231 // registered in either mock backend. 232 err := wrapper.UpdateWorkload(&serviceregistration.WorkloadServices{}, 233 &serviceregistration.WorkloadServices{}) 234 require.NoError(t, err) 235 require.Len(t, consul.GetOps(), 0) 236 require.Len(t, nomad.GetOps(), 0) 237 238 }, 239 name: "zero new or old", 240 }, 241 { 242 testFn: func(t *testing.T) { 243 244 // Generate the test wrapper and provider mocks. 245 wrapper, consul, nomad := setupTestWrapper() 246 247 // Create a single workload that we can use twice, using the 248 // consul provider. 249 workload := serviceregistration.WorkloadServices{ 250 Services: []*structs.Service{ 251 { 252 Provider: structs.ServiceProviderConsul, 253 }, 254 }, 255 } 256 257 // Call the function and ensure the consul backend has the 258 // expected operations. 259 require.NoError(t, wrapper.UpdateWorkload(&workload, &workload)) 260 require.Len(t, nomad.GetOps(), 0) 261 262 consulOps := consul.GetOps() 263 require.Len(t, consulOps, 1) 264 require.Equal(t, "update", consulOps[0].Op) 265 }, 266 name: "consul new and old", 267 }, 268 { 269 testFn: func(t *testing.T) { 270 271 // Generate the test wrapper and provider mocks. 272 wrapper, consul, nomad := setupTestWrapper() 273 274 // Create a single workload that we can use twice, using the 275 // nomad provider. 276 workload := serviceregistration.WorkloadServices{ 277 Services: []*structs.Service{ 278 { 279 Provider: structs.ServiceProviderNomad, 280 }, 281 }, 282 } 283 284 // Call the function and ensure the nomad backend has the 285 // expected operations. 286 require.NoError(t, wrapper.UpdateWorkload(&workload, &workload)) 287 require.Len(t, consul.GetOps(), 0) 288 289 nomadOps := nomad.GetOps() 290 require.Len(t, nomadOps, 1) 291 require.Equal(t, "update", nomadOps[0].Op) 292 }, 293 name: "nomad new and old", 294 }, 295 { 296 testFn: func(t *testing.T) { 297 298 // Generate the test wrapper and provider mocks. 299 wrapper, consul, nomad := setupTestWrapper() 300 301 // Create each workload. 302 newWorkload := serviceregistration.WorkloadServices{ 303 Services: []*structs.Service{ 304 { 305 Provider: structs.ServiceProviderNomad, 306 }, 307 }, 308 } 309 310 oldWorkload := serviceregistration.WorkloadServices{ 311 Services: []*structs.Service{ 312 { 313 Provider: structs.ServiceProviderConsul, 314 }, 315 }, 316 } 317 318 // Call the function and ensure the backends have the expected 319 // operations. 320 require.NoError(t, wrapper.UpdateWorkload(&oldWorkload, &newWorkload)) 321 322 nomadOps := nomad.GetOps() 323 require.Len(t, nomadOps, 1) 324 require.Equal(t, "add", nomadOps[0].Op) 325 326 consulOps := consul.GetOps() 327 require.Len(t, consulOps, 1) 328 require.Equal(t, "remove", consulOps[0].Op) 329 }, 330 name: "nomad new and consul old", 331 }, 332 { 333 testFn: func(t *testing.T) { 334 335 // Generate the test wrapper and provider mocks. 336 wrapper, consul, nomad := setupTestWrapper() 337 338 // Create each workload. 339 newWorkload := serviceregistration.WorkloadServices{ 340 Services: []*structs.Service{ 341 { 342 Provider: structs.ServiceProviderConsul, 343 }, 344 }, 345 } 346 347 oldWorkload := serviceregistration.WorkloadServices{ 348 Services: []*structs.Service{ 349 { 350 Provider: structs.ServiceProviderNomad, 351 }, 352 }, 353 } 354 355 // Call the function and ensure the backends have the expected 356 // operations. 357 require.NoError(t, wrapper.UpdateWorkload(&oldWorkload, &newWorkload)) 358 359 nomadOps := nomad.GetOps() 360 require.Len(t, nomadOps, 1) 361 require.Equal(t, "remove", nomadOps[0].Op) 362 363 consulOps := consul.GetOps() 364 require.Len(t, consulOps, 1) 365 require.Equal(t, "add", consulOps[0].Op) 366 }, 367 name: "consul new and nomad old", 368 }, 369 } 370 371 for _, tc := range testCases { 372 t.Run(tc.name, func(t *testing.T) { 373 tc.testFn(t) 374 }) 375 } 376 } 377 378 func setupTestWrapper() (*HandlerWrapper, *regMock.ServiceRegistrationHandler, *regMock.ServiceRegistrationHandler) { 379 log := hclog.NewNullLogger() 380 consulMock := regMock.NewServiceRegistrationHandler(log) 381 nomadMock := regMock.NewServiceRegistrationHandler(log) 382 wrapper := NewHandlerWrapper(log, consulMock, nomadMock) 383 return wrapper, consulMock, nomadMock 384 }