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  }