github.com/iqoqo/nomad@v0.11.3-0.20200911112621-d7021c74d101/client/allocrunner/groupservice_hook_test.go (about) 1 package allocrunner 2 3 import ( 4 "io/ioutil" 5 "testing" 6 "time" 7 8 consulapi "github.com/hashicorp/consul/api" 9 ctestutil "github.com/hashicorp/consul/sdk/testutil" 10 "github.com/hashicorp/nomad/client/allocrunner/interfaces" 11 "github.com/hashicorp/nomad/client/consul" 12 "github.com/hashicorp/nomad/client/taskenv" 13 agentconsul "github.com/hashicorp/nomad/command/agent/consul" 14 "github.com/hashicorp/nomad/helper" 15 "github.com/hashicorp/nomad/helper/testlog" 16 "github.com/hashicorp/nomad/nomad/mock" 17 "github.com/hashicorp/nomad/nomad/structs" 18 "github.com/stretchr/testify/require" 19 ) 20 21 var _ interfaces.RunnerPrerunHook = (*groupServiceHook)(nil) 22 var _ interfaces.RunnerUpdateHook = (*groupServiceHook)(nil) 23 var _ interfaces.RunnerPostrunHook = (*groupServiceHook)(nil) 24 var _ interfaces.RunnerPreKillHook = (*groupServiceHook)(nil) 25 26 // TestGroupServiceHook_NoGroupServices asserts calling group service hooks 27 // without group services does not error. 28 func TestGroupServiceHook_NoGroupServices(t *testing.T) { 29 t.Parallel() 30 31 alloc := mock.Alloc() 32 alloc.Job.TaskGroups[0].Services = []*structs.Service{{ 33 Name: "foo", 34 PortLabel: "9999", 35 }} 36 logger := testlog.HCLogger(t) 37 consulClient := consul.NewMockConsulServiceClient(t, logger) 38 39 h := newGroupServiceHook(groupServiceHookConfig{ 40 alloc: alloc, 41 consul: consulClient, 42 restarter: agentconsul.NoopRestarter(), 43 taskEnvBuilder: taskenv.NewBuilder(mock.Node(), alloc, nil, alloc.Job.Region), 44 logger: logger, 45 }) 46 require.NoError(t, h.Prerun()) 47 48 req := &interfaces.RunnerUpdateRequest{Alloc: alloc} 49 require.NoError(t, h.Update(req)) 50 51 require.NoError(t, h.Postrun()) 52 53 ops := consulClient.GetOps() 54 require.Len(t, ops, 4) 55 require.Equal(t, "add", ops[0].Op) 56 require.Equal(t, "update", ops[1].Op) 57 require.Equal(t, "remove", ops[2].Op) 58 } 59 60 // TestGroupServiceHook_ShutdownDelayUpdate asserts calling group service hooks 61 // update updates the hooks delay value. 62 func TestGroupServiceHook_ShutdownDelayUpdate(t *testing.T) { 63 t.Parallel() 64 65 alloc := mock.Alloc() 66 alloc.Job.TaskGroups[0].ShutdownDelay = helper.TimeToPtr(10 * time.Second) 67 68 logger := testlog.HCLogger(t) 69 consulClient := consul.NewMockConsulServiceClient(t, logger) 70 71 h := newGroupServiceHook(groupServiceHookConfig{ 72 alloc: alloc, 73 consul: consulClient, 74 restarter: agentconsul.NoopRestarter(), 75 taskEnvBuilder: taskenv.NewBuilder(mock.Node(), alloc, nil, alloc.Job.Region), 76 logger: logger, 77 }) 78 require.NoError(t, h.Prerun()) 79 80 // Incease shutdown Delay 81 alloc.Job.TaskGroups[0].ShutdownDelay = helper.TimeToPtr(15 * time.Second) 82 req := &interfaces.RunnerUpdateRequest{Alloc: alloc} 83 require.NoError(t, h.Update(req)) 84 85 // Assert that update updated the delay value 86 require.Equal(t, h.delay, 15*time.Second) 87 88 // Remove shutdown delay 89 alloc.Job.TaskGroups[0].ShutdownDelay = nil 90 req = &interfaces.RunnerUpdateRequest{Alloc: alloc} 91 require.NoError(t, h.Update(req)) 92 93 // Assert that update updated the delay value 94 require.Equal(t, h.delay, 0*time.Second) 95 } 96 97 // TestGroupServiceHook_GroupServices asserts group service hooks with group 98 // services does not error. 99 func TestGroupServiceHook_GroupServices(t *testing.T) { 100 t.Parallel() 101 102 alloc := mock.ConnectAlloc() 103 logger := testlog.HCLogger(t) 104 consulClient := consul.NewMockConsulServiceClient(t, logger) 105 106 h := newGroupServiceHook(groupServiceHookConfig{ 107 alloc: alloc, 108 consul: consulClient, 109 restarter: agentconsul.NoopRestarter(), 110 taskEnvBuilder: taskenv.NewBuilder(mock.Node(), alloc, nil, alloc.Job.Region), 111 logger: logger, 112 }) 113 require.NoError(t, h.Prerun()) 114 115 req := &interfaces.RunnerUpdateRequest{Alloc: alloc} 116 require.NoError(t, h.Update(req)) 117 118 require.NoError(t, h.Postrun()) 119 120 ops := consulClient.GetOps() 121 require.Len(t, ops, 4) 122 require.Equal(t, "add", ops[0].Op) 123 require.Equal(t, "update", ops[1].Op) 124 require.Equal(t, "remove", ops[2].Op) 125 } 126 127 // TestGroupServiceHook_Error asserts group service hooks with group 128 // services but no group network returns an error. 129 func TestGroupServiceHook_NoNetwork(t *testing.T) { 130 t.Parallel() 131 132 alloc := mock.Alloc() 133 alloc.Job.TaskGroups[0].Networks = []*structs.NetworkResource{} 134 tg := alloc.Job.LookupTaskGroup(alloc.TaskGroup) 135 tg.Services = []*structs.Service{ 136 { 137 Name: "testconnect", 138 PortLabel: "9999", 139 Connect: &structs.ConsulConnect{ 140 SidecarService: &structs.ConsulSidecarService{}, 141 }, 142 }, 143 } 144 logger := testlog.HCLogger(t) 145 146 consulClient := consul.NewMockConsulServiceClient(t, logger) 147 148 h := newGroupServiceHook(groupServiceHookConfig{ 149 alloc: alloc, 150 consul: consulClient, 151 restarter: agentconsul.NoopRestarter(), 152 taskEnvBuilder: taskenv.NewBuilder(mock.Node(), alloc, nil, alloc.Job.Region), 153 logger: logger, 154 }) 155 require.NoError(t, h.Prerun()) 156 157 req := &interfaces.RunnerUpdateRequest{Alloc: alloc} 158 require.NoError(t, h.Update(req)) 159 160 require.NoError(t, h.Postrun()) 161 162 ops := consulClient.GetOps() 163 require.Len(t, ops, 4) 164 require.Equal(t, "add", ops[0].Op) 165 require.Equal(t, "update", ops[1].Op) 166 require.Equal(t, "remove", ops[2].Op) 167 } 168 169 func TestGroupServiceHook_getWorkloadServices(t *testing.T) { 170 t.Parallel() 171 172 alloc := mock.Alloc() 173 alloc.Job.TaskGroups[0].Networks = []*structs.NetworkResource{} 174 tg := alloc.Job.LookupTaskGroup(alloc.TaskGroup) 175 tg.Services = []*structs.Service{ 176 { 177 Name: "testconnect", 178 PortLabel: "9999", 179 Connect: &structs.ConsulConnect{ 180 SidecarService: &structs.ConsulSidecarService{}, 181 }, 182 }, 183 } 184 logger := testlog.HCLogger(t) 185 186 consulClient := consul.NewMockConsulServiceClient(t, logger) 187 188 h := newGroupServiceHook(groupServiceHookConfig{ 189 alloc: alloc, 190 consul: consulClient, 191 restarter: agentconsul.NoopRestarter(), 192 taskEnvBuilder: taskenv.NewBuilder(mock.Node(), alloc, nil, alloc.Job.Region), 193 logger: logger, 194 }) 195 196 services := h.getWorkloadServices() 197 require.Len(t, services.Services, 1) 198 } 199 200 // TestGroupServiceHook_Update08Alloc asserts that adding group services to a previously 201 // 0.8 alloc works. 202 // 203 // COMPAT(0.11) Only valid for upgrades from 0.8. 204 func TestGroupServiceHook_Update08Alloc(t *testing.T) { 205 // Create an embedded Consul server 206 testconsul, err := ctestutil.NewTestServerConfig(func(c *ctestutil.TestServerConfig) { 207 // If -v wasn't specified squelch consul logging 208 if !testing.Verbose() { 209 c.Stdout = ioutil.Discard 210 c.Stderr = ioutil.Discard 211 } 212 }) 213 if err != nil { 214 t.Fatalf("error starting test consul server: %v", err) 215 } 216 defer testconsul.Stop() 217 218 consulConfig := consulapi.DefaultConfig() 219 consulConfig.Address = testconsul.HTTPAddr 220 consulClient, err := consulapi.NewClient(consulConfig) 221 require.NoError(t, err) 222 serviceClient := agentconsul.NewServiceClient(consulClient.Agent(), testlog.HCLogger(t), true) 223 224 // Lower periodicInterval to ensure periodic syncing doesn't improperly 225 // remove Connect services. 226 //const interval = 50 * time.Millisecond 227 //serviceClient.periodicInterval = interval 228 229 // Disable deregistration probation to test syncing 230 //serviceClient.deregisterProbationExpiry = time.Time{} 231 232 go serviceClient.Run() 233 defer serviceClient.Shutdown() 234 235 // Create new 0.10-style alloc 236 alloc := mock.Alloc() 237 alloc.AllocatedResources.Shared.Networks = []*structs.NetworkResource{ 238 { 239 Mode: "bridge", 240 IP: "10.0.0.1", 241 DynamicPorts: []structs.Port{ 242 { 243 Label: "connect-proxy-testconnect", 244 Value: 9999, 245 To: 9998, 246 }, 247 }, 248 }, 249 } 250 tg := alloc.Job.LookupTaskGroup(alloc.TaskGroup) 251 tg.Services = []*structs.Service{ 252 { 253 Name: "testconnect", 254 PortLabel: "9999", 255 Connect: &structs.ConsulConnect{ 256 SidecarService: &structs.ConsulSidecarService{ 257 Proxy: &structs.ConsulProxy{ 258 LocalServicePort: 9000, 259 }, 260 }, 261 }, 262 }, 263 } 264 265 // Create old 0.8-style alloc from new alloc 266 oldAlloc := alloc.Copy() 267 oldAlloc.AllocatedResources = nil 268 oldAlloc.Job.LookupTaskGroup(alloc.TaskGroup).Services = nil 269 270 // Create the group service hook 271 h := newGroupServiceHook(groupServiceHookConfig{ 272 alloc: oldAlloc, 273 consul: serviceClient, 274 restarter: agentconsul.NoopRestarter(), 275 taskEnvBuilder: taskenv.NewBuilder(mock.Node(), oldAlloc, nil, oldAlloc.Job.Region), 276 logger: testlog.HCLogger(t), 277 }) 278 279 require.NoError(t, h.Prerun()) 280 require.NoError(t, h.Update(&interfaces.RunnerUpdateRequest{Alloc: alloc})) 281 282 // Assert the group and sidecar services are registered 283 require.Eventually(t, func() bool { 284 services, err := consulClient.Agent().Services() 285 require.NoError(t, err) 286 return len(services) == 2 287 }, 3*time.Second, 100*time.Millisecond) 288 289 }