github.imxd.top/hashicorp/consul@v1.4.5/api/health_test.go (about) 1 package api 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/hashicorp/consul/testutil" 8 "github.com/hashicorp/consul/testutil/retry" 9 "github.com/pascaldekloe/goe/verify" 10 "github.com/stretchr/testify/require" 11 ) 12 13 func TestAPI_HealthNode(t *testing.T) { 14 t.Parallel() 15 c, s := makeClient(t) 16 defer s.Stop() 17 18 agent := c.Agent() 19 health := c.Health() 20 21 info, err := agent.Self() 22 if err != nil { 23 t.Fatalf("err: %v", err) 24 } 25 name := info["Config"]["NodeName"].(string) 26 retry.Run(t, func(r *retry.R) { 27 checks, meta, err := health.Node(name, nil) 28 if err != nil { 29 r.Fatal(err) 30 } 31 if meta.LastIndex == 0 { 32 r.Fatalf("bad: %v", meta) 33 } 34 if len(checks) == 0 { 35 r.Fatalf("bad: %v", checks) 36 } 37 }) 38 } 39 40 func TestAPI_HealthChecks_AggregatedStatus(t *testing.T) { 41 t.Parallel() 42 43 cases := []struct { 44 name string 45 checks HealthChecks 46 exp string 47 }{ 48 { 49 "empty", 50 nil, 51 HealthPassing, 52 }, 53 { 54 "passing", 55 HealthChecks{ 56 &HealthCheck{ 57 Status: HealthPassing, 58 }, 59 }, 60 HealthPassing, 61 }, 62 { 63 "warning", 64 HealthChecks{ 65 &HealthCheck{ 66 Status: HealthWarning, 67 }, 68 }, 69 HealthWarning, 70 }, 71 { 72 "critical", 73 HealthChecks{ 74 &HealthCheck{ 75 Status: HealthCritical, 76 }, 77 }, 78 HealthCritical, 79 }, 80 { 81 "node_maintenance", 82 HealthChecks{ 83 &HealthCheck{ 84 CheckID: NodeMaint, 85 }, 86 }, 87 HealthMaint, 88 }, 89 { 90 "service_maintenance", 91 HealthChecks{ 92 &HealthCheck{ 93 CheckID: ServiceMaintPrefix + "service", 94 }, 95 }, 96 HealthMaint, 97 }, 98 { 99 "unknown", 100 HealthChecks{ 101 &HealthCheck{ 102 Status: "nope-nope-noper", 103 }, 104 }, 105 "", 106 }, 107 { 108 "maintenance_over_critical", 109 HealthChecks{ 110 &HealthCheck{ 111 CheckID: NodeMaint, 112 }, 113 &HealthCheck{ 114 Status: HealthCritical, 115 }, 116 }, 117 HealthMaint, 118 }, 119 { 120 "critical_over_warning", 121 HealthChecks{ 122 &HealthCheck{ 123 Status: HealthCritical, 124 }, 125 &HealthCheck{ 126 Status: HealthWarning, 127 }, 128 }, 129 HealthCritical, 130 }, 131 { 132 "warning_over_passing", 133 HealthChecks{ 134 &HealthCheck{ 135 Status: HealthWarning, 136 }, 137 &HealthCheck{ 138 Status: HealthPassing, 139 }, 140 }, 141 HealthWarning, 142 }, 143 { 144 "lots", 145 HealthChecks{ 146 &HealthCheck{ 147 Status: HealthPassing, 148 }, 149 &HealthCheck{ 150 Status: HealthPassing, 151 }, 152 &HealthCheck{ 153 Status: HealthPassing, 154 }, 155 &HealthCheck{ 156 Status: HealthWarning, 157 }, 158 }, 159 HealthWarning, 160 }, 161 } 162 163 for i, tc := range cases { 164 t.Run(fmt.Sprintf("%d_%s", i, tc.name), func(t *testing.T) { 165 act := tc.checks.AggregatedStatus() 166 if tc.exp != act { 167 t.Errorf("\nexp: %#v\nact: %#v", tc.exp, act) 168 } 169 }) 170 } 171 } 172 173 func TestAPI_HealthChecks(t *testing.T) { 174 t.Parallel() 175 c, s := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) { 176 conf.NodeName = "node123" 177 }) 178 defer s.Stop() 179 180 agent := c.Agent() 181 health := c.Health() 182 183 // Make a service with a check 184 reg := &AgentServiceRegistration{ 185 Name: "foo", 186 Tags: []string{"bar"}, 187 Check: &AgentServiceCheck{ 188 TTL: "15s", 189 }, 190 } 191 if err := agent.ServiceRegister(reg); err != nil { 192 t.Fatalf("err: %v", err) 193 } 194 defer agent.ServiceDeregister("foo") 195 196 retry.Run(t, func(r *retry.R) { 197 checks := HealthChecks{ 198 &HealthCheck{ 199 Node: "node123", 200 CheckID: "service:foo", 201 Name: "Service 'foo' check", 202 Status: "critical", 203 ServiceID: "foo", 204 ServiceName: "foo", 205 ServiceTags: []string{"bar"}, 206 }, 207 } 208 209 out, meta, err := health.Checks("foo", nil) 210 if err != nil { 211 r.Fatal(err) 212 } 213 if meta.LastIndex == 0 { 214 r.Fatalf("bad: %v", meta) 215 } 216 checks[0].CreateIndex = out[0].CreateIndex 217 checks[0].ModifyIndex = out[0].ModifyIndex 218 verify.Values(r, "checks", out, checks) 219 }) 220 } 221 222 func TestAPI_HealthChecks_NodeMetaFilter(t *testing.T) { 223 t.Parallel() 224 meta := map[string]string{"somekey": "somevalue"} 225 c, s := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) { 226 conf.NodeMeta = meta 227 }) 228 defer s.Stop() 229 230 agent := c.Agent() 231 health := c.Health() 232 233 // Make a service with a check 234 reg := &AgentServiceRegistration{ 235 Name: "foo", 236 Check: &AgentServiceCheck{ 237 TTL: "15s", 238 }, 239 } 240 if err := agent.ServiceRegister(reg); err != nil { 241 t.Fatalf("err: %v", err) 242 } 243 defer agent.ServiceDeregister("foo") 244 245 retry.Run(t, func(r *retry.R) { 246 checks, meta, err := health.Checks("foo", &QueryOptions{NodeMeta: meta}) 247 if err != nil { 248 r.Fatal(err) 249 } 250 if meta.LastIndex == 0 { 251 r.Fatalf("bad: %v", meta) 252 } 253 if len(checks) == 0 { 254 r.Fatalf("Bad: %v", checks) 255 } 256 }) 257 } 258 259 func TestAPI_HealthService(t *testing.T) { 260 t.Parallel() 261 c, s := makeClient(t) 262 defer s.Stop() 263 264 health := c.Health() 265 retry.Run(t, func(r *retry.R) { 266 // consul service should always exist... 267 checks, meta, err := health.Service("consul", "", true, nil) 268 if err != nil { 269 r.Fatal(err) 270 } 271 if meta.LastIndex == 0 { 272 r.Fatalf("bad: %v", meta) 273 } 274 if len(checks) == 0 { 275 r.Fatalf("Bad: %v", checks) 276 } 277 if _, ok := checks[0].Node.TaggedAddresses["wan"]; !ok { 278 r.Fatalf("Bad: %v", checks[0].Node) 279 } 280 if checks[0].Node.Datacenter != "dc1" { 281 r.Fatalf("Bad datacenter: %v", checks[0].Node) 282 } 283 }) 284 } 285 286 func TestAPI_HealthService_SingleTag(t *testing.T) { 287 t.Parallel() 288 c, s := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) { 289 conf.NodeName = "node123" 290 }) 291 defer s.Stop() 292 agent := c.Agent() 293 health := c.Health() 294 reg := &AgentServiceRegistration{ 295 Name: "foo", 296 ID: "foo1", 297 Tags: []string{"bar"}, 298 Check: &AgentServiceCheck{ 299 Status: HealthPassing, 300 TTL: "15s", 301 }, 302 } 303 require.NoError(t, agent.ServiceRegister(reg)) 304 defer agent.ServiceDeregister("foo1") 305 retry.Run(t, func(r *retry.R) { 306 services, meta, err := health.Service("foo", "bar", true, nil) 307 require.NoError(t, err) 308 require.NotEqual(t, meta.LastIndex, 0) 309 require.Len(t, services, 1) 310 require.Equal(t, services[0].Service.ID, "foo1") 311 }) 312 } 313 func TestAPI_HealthService_MultipleTags(t *testing.T) { 314 t.Parallel() 315 c, s := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) { 316 conf.NodeName = "node123" 317 }) 318 defer s.Stop() 319 320 agent := c.Agent() 321 health := c.Health() 322 323 // Make two services with a check 324 reg := &AgentServiceRegistration{ 325 Name: "foo", 326 ID: "foo1", 327 Tags: []string{"bar"}, 328 Check: &AgentServiceCheck{ 329 Status: HealthPassing, 330 TTL: "15s", 331 }, 332 } 333 require.NoError(t, agent.ServiceRegister(reg)) 334 defer agent.ServiceDeregister("foo1") 335 336 reg2 := &AgentServiceRegistration{ 337 Name: "foo", 338 ID: "foo2", 339 Tags: []string{"bar", "v2"}, 340 Check: &AgentServiceCheck{ 341 Status: HealthPassing, 342 TTL: "15s", 343 }, 344 } 345 require.NoError(t, agent.ServiceRegister(reg2)) 346 defer agent.ServiceDeregister("foo2") 347 348 // Test searching with one tag (two results) 349 retry.Run(t, func(r *retry.R) { 350 services, meta, err := health.ServiceMultipleTags("foo", []string{"bar"}, true, nil) 351 352 require.NoError(t, err) 353 require.NotEqual(t, meta.LastIndex, 0) 354 require.Len(t, services, 2) 355 }) 356 357 // Test searching with two tags (one result) 358 retry.Run(t, func(r *retry.R) { 359 services, meta, err := health.ServiceMultipleTags("foo", []string{"bar", "v2"}, true, nil) 360 361 require.NoError(t, err) 362 require.NotEqual(t, meta.LastIndex, 0) 363 require.Len(t, services, 1) 364 require.Equal(t, services[0].Service.ID, "foo2") 365 }) 366 } 367 368 func TestAPI_HealthService_NodeMetaFilter(t *testing.T) { 369 t.Parallel() 370 meta := map[string]string{"somekey": "somevalue"} 371 c, s := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) { 372 conf.NodeMeta = meta 373 }) 374 defer s.Stop() 375 376 health := c.Health() 377 retry.Run(t, func(r *retry.R) { 378 // consul service should always exist... 379 checks, meta, err := health.Service("consul", "", true, &QueryOptions{NodeMeta: meta}) 380 require.NoError(t, err) 381 require.NotEqual(t, meta.LastIndex, 0) 382 require.NotEqual(t, len(checks), 0) 383 require.Equal(t, checks[0].Node.Datacenter, "dc1") 384 require.Contains(t, checks[0].Node.TaggedAddresses, "wan") 385 }) 386 } 387 388 func TestAPI_HealthConnect(t *testing.T) { 389 t.Parallel() 390 c, s := makeClient(t) 391 defer s.Stop() 392 393 agent := c.Agent() 394 health := c.Health() 395 396 // Make a service with a proxy 397 reg := &AgentServiceRegistration{ 398 Name: "foo", 399 Port: 8000, 400 } 401 err := agent.ServiceRegister(reg) 402 require.NoError(t, err) 403 defer agent.ServiceDeregister("foo") 404 405 // Register the proxy 406 proxyReg := &AgentServiceRegistration{ 407 Name: "foo-proxy", 408 Port: 8001, 409 Kind: ServiceKindConnectProxy, 410 Proxy: &AgentServiceConnectProxyConfig{ 411 DestinationServiceName: "foo", 412 }, 413 } 414 err = agent.ServiceRegister(proxyReg) 415 require.NoError(t, err) 416 defer agent.ServiceDeregister("foo-proxy") 417 418 retry.Run(t, func(r *retry.R) { 419 services, meta, err := health.Connect("foo", "", true, nil) 420 if err != nil { 421 r.Fatal(err) 422 } 423 if meta.LastIndex == 0 { 424 r.Fatalf("bad: %v", meta) 425 } 426 // Should be exactly 1 service - the original shouldn't show up as a connect 427 // endpoint, only it's proxy. 428 if len(services) != 1 { 429 r.Fatalf("Bad: %v", services) 430 } 431 if services[0].Node.Datacenter != "dc1" { 432 r.Fatalf("Bad datacenter: %v", services[0].Node) 433 } 434 if services[0].Service.Port != proxyReg.Port { 435 r.Fatalf("Bad port: %v", services[0]) 436 } 437 }) 438 } 439 440 func TestAPI_HealthState(t *testing.T) { 441 t.Parallel() 442 c, s := makeClient(t) 443 defer s.Stop() 444 445 health := c.Health() 446 retry.Run(t, func(r *retry.R) { 447 checks, meta, err := health.State("any", nil) 448 if err != nil { 449 r.Fatal(err) 450 } 451 if meta.LastIndex == 0 { 452 r.Fatalf("bad: %v", meta) 453 } 454 if len(checks) == 0 { 455 r.Fatalf("Bad: %v", checks) 456 } 457 }) 458 } 459 460 func TestAPI_HealthState_NodeMetaFilter(t *testing.T) { 461 t.Parallel() 462 meta := map[string]string{"somekey": "somevalue"} 463 c, s := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) { 464 conf.NodeMeta = meta 465 }) 466 defer s.Stop() 467 468 health := c.Health() 469 retry.Run(t, func(r *retry.R) { 470 checks, meta, err := health.State("any", &QueryOptions{NodeMeta: meta}) 471 if err != nil { 472 r.Fatal(err) 473 } 474 if meta.LastIndex == 0 { 475 r.Fatalf("bad: %v", meta) 476 } 477 if len(checks) == 0 { 478 r.Fatalf("Bad: %v", checks) 479 } 480 }) 481 }