From ff1146702236a9b456d32a89db86cb8e3c55c5d7 Mon Sep 17 00:00:00 2001 From: Christoph Glaubitz Date: Thu, 10 Aug 2017 18:00:31 +0200 Subject: [PATCH] Bind healthcheck to backend by entryPointName --- .../healthcheck/multiple-entrypoints-drr.toml | 31 +++++++ .../healthcheck/multiple-entrypoints-wrr.toml | 31 +++++++ integration/healthcheck_test.go | 89 +++++++++++++++++-- server/server.go | 4 +- 4 files changed, 144 insertions(+), 11 deletions(-) create mode 100644 integration/fixtures/healthcheck/multiple-entrypoints-drr.toml create mode 100644 integration/fixtures/healthcheck/multiple-entrypoints-wrr.toml diff --git a/integration/fixtures/healthcheck/multiple-entrypoints-drr.toml b/integration/fixtures/healthcheck/multiple-entrypoints-drr.toml new file mode 100644 index 000000000..7ebf72621 --- /dev/null +++ b/integration/fixtures/healthcheck/multiple-entrypoints-drr.toml @@ -0,0 +1,31 @@ +defaultEntryPoints = ["http1", "http2"] + +logLevel = "DEBUG" + +[entryPoints] + [entryPoints.http1] + address = ":8000" + [entryPoints.http2] + address = ":9000" + +[web] + address = ":8080" + +[file] +[backends] + [backends.backend1] + [backends.backend1.LoadBalancer] + method = "drr" + [backends.backend1.healthcheck] + path = "/health" + interval = "1s" + [backends.backend1.servers.server1] + url = "http://{{.Server1}}:80" + [backends.backend1.servers.server2] + url = "http://{{.Server2}}:80" + +[frontends] + [frontends.frontend1] + backend = "backend1" + [frontends.frontend1.routes.test_1] + rule = "Host:test.localhost" diff --git a/integration/fixtures/healthcheck/multiple-entrypoints-wrr.toml b/integration/fixtures/healthcheck/multiple-entrypoints-wrr.toml new file mode 100644 index 000000000..c6e4ddfe7 --- /dev/null +++ b/integration/fixtures/healthcheck/multiple-entrypoints-wrr.toml @@ -0,0 +1,31 @@ +defaultEntryPoints = ["http1", "http2"] + +logLevel = "DEBUG" + +[entryPoints] + [entryPoints.http1] + address = ":8000" + [entryPoints.http2] + address = ":9000" + +[web] + address = ":8080" + +[file] +[backends] + [backends.backend1] + [backends.backend1.LoadBalancer] + method = "wrr" + [backends.backend1.healthcheck] + path = "/health" + interval = "1s" + [backends.backend1.servers.server1] + url = "http://{{.Server1}}:80" + [backends.backend1.servers.server2] + url = "http://{{.Server2}}:80" + +[frontends] + [frontends.frontend1] + backend = "backend1" + [frontends.frontend1.routes.test_1] + rule = "Host:test.localhost" diff --git a/integration/healthcheck_test.go b/integration/healthcheck_test.go index 098447752..37205ce78 100644 --- a/integration/healthcheck_test.go +++ b/integration/healthcheck_test.go @@ -12,22 +12,26 @@ import ( ) // HealthCheck test suites (using libcompose) -type HealthCheckSuite struct{ BaseSuite } +type HealthCheckSuite struct { + BaseSuite + whoami1IP string + whoami2IP string +} func (s *HealthCheckSuite) SetUpSuite(c *check.C) { s.createComposeProject(c, "healthcheck") s.composeProject.Start(c) + + s.whoami1IP = s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + s.whoami2IP = s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress } func (s *HealthCheckSuite) TestSimpleConfiguration(c *check.C) { - whoami1Host := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress - whoami2Host := s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress - file := s.adaptFile(c, "fixtures/healthcheck/simple.toml", struct { Server1 string Server2 string - }{whoami1Host, whoami2Host}) + }{s.whoami1IP, s.whoami2IP}) defer os.Remove(file) cmd, _ := s.cmdTraefik(withConfigFile(file)) @@ -48,7 +52,7 @@ func (s *HealthCheckSuite) TestSimpleConfiguration(c *check.C) { // Fix all whoami health to 500 client := &http.Client{} - whoamiHosts := []string{whoami1Host, whoami2Host} + whoamiHosts := []string{s.whoami1IP, s.whoami2IP} for _, whoami := range whoamiHosts { statusInternalServerErrorReq, err := http.NewRequest(http.MethodPost, "http://"+whoami+"/health", bytes.NewBuffer([]byte("500"))) c.Assert(err, checker.IsNil) @@ -64,7 +68,7 @@ func (s *HealthCheckSuite) TestSimpleConfiguration(c *check.C) { c.Assert(err, checker.IsNil) // Change one whoami health to 200 - statusOKReq1, err := http.NewRequest(http.MethodPost, "http://"+whoami1Host+"/health", bytes.NewBuffer([]byte("200"))) + statusOKReq1, err := http.NewRequest(http.MethodPost, "http://"+s.whoami1IP+"/health", bytes.NewBuffer([]byte("200"))) c.Assert(err, checker.IsNil) _, err = client.Do(statusOKReq1) c.Assert(err, checker.IsNil) @@ -78,11 +82,11 @@ func (s *HealthCheckSuite) TestSimpleConfiguration(c *check.C) { frontendReq.Host = "test.localhost" // Check if whoami1 responds - err = try.Request(frontendReq, 500*time.Millisecond, try.BodyContains(whoami1Host)) + err = try.Request(frontendReq, 500*time.Millisecond, try.BodyContains(s.whoami1IP)) c.Assert(err, checker.IsNil) // Check if the service with bad health check (whoami2) never respond. - err = try.Request(frontendReq, 2*time.Second, try.BodyContains(whoami2Host)) + err = try.Request(frontendReq, 2*time.Second, try.BodyContains(s.whoami2IP)) c.Assert(err, checker.Not(checker.IsNil)) // TODO validate : run on 80 @@ -92,3 +96,70 @@ func (s *HealthCheckSuite) TestSimpleConfiguration(c *check.C) { c.Assert(err, checker.IsNil) c.Assert(resp.StatusCode, checker.Equals, http.StatusNotFound) } + +func (s *HealthCheckSuite) TestMultipleEntrypointsWrr(c *check.C) { + s.doTestMultipleEntrypoints(c, "fixtures/healthcheck/multiple-entrypoints-wrr.toml") +} + +func (s *HealthCheckSuite) TestMultipleEntrypointsDrr(c *check.C) { + s.doTestMultipleEntrypoints(c, "fixtures/healthcheck/multiple-entrypoints-drr.toml") +} + +func (s *HealthCheckSuite) doTestMultipleEntrypoints(c *check.C, fixture string) { + file := s.adaptFile(c, fixture, struct { + Server1 string + Server2 string + }{s.whoami1IP, s.whoami2IP}) + defer os.Remove(file) + + cmd, _ := s.cmdTraefik(withConfigFile(file)) + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer cmd.Process.Kill() + + // Wait for traefik + err = try.GetRequest("http://localhost:8080/api/providers", 60*time.Second, try.BodyContains("Host:test.localhost")) + c.Assert(err, checker.IsNil) + + // Check entrypoint http1 + frontendHealthReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/health", nil) + c.Assert(err, checker.IsNil) + frontendHealthReq.Host = "test.localhost" + + err = try.Request(frontendHealthReq, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK)) + c.Assert(err, checker.IsNil) + + // Check entrypoint http2 + frontendHealthReq, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:9000/health", nil) + c.Assert(err, checker.IsNil) + frontendHealthReq.Host = "test.localhost" + + err = try.Request(frontendHealthReq, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK)) + c.Assert(err, checker.IsNil) + + // Set one whoami health to 500 + client := &http.Client{} + statusInternalServerErrorReq, err := http.NewRequest(http.MethodPost, "http://"+s.whoami1IP+"/health", bytes.NewBuffer([]byte("500"))) + c.Assert(err, checker.IsNil) + _, err = client.Do(statusInternalServerErrorReq) + c.Assert(err, checker.IsNil) + + // Waiting for Traefik healthcheck + try.Sleep(2 * time.Second) + + frontend1Req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil) + c.Assert(err, checker.IsNil) + frontend1Req.Host = "test.localhost" + + frontend2Req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:9000/", nil) + c.Assert(err, checker.IsNil) + frontend2Req.Host = "test.localhost" + + // Check if whoami1 never responds + err = try.Request(frontend2Req, 2*time.Second, try.BodyContains(s.whoami1IP)) + c.Assert(err, checker.Not(checker.IsNil)) + + // Check if whoami1 never responds + err = try.Request(frontend1Req, 2*time.Second, try.BodyContains(s.whoami1IP)) + c.Assert(err, checker.Not(checker.IsNil)) +} diff --git a/server/server.go b/server/server.go index d270487ef..23d6a1850 100644 --- a/server/server.go +++ b/server/server.go @@ -744,7 +744,7 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo hcOpts := parseHealthCheckOptions(rebalancer, frontend.Backend, configuration.Backends[frontend.Backend].HealthCheck, globalConfiguration.HealthCheck) if hcOpts != nil { log.Debugf("Setting up backend health check %s", *hcOpts) - backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(*hcOpts) + backendsHealthcheck[entryPointName+frontend.Backend] = healthcheck.NewBackendHealthCheck(*hcOpts) } lb = middlewares.NewEmptyBackendHandler(rebalancer, lb) case types.Wrr: @@ -765,7 +765,7 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo hcOpts := parseHealthCheckOptions(rr, frontend.Backend, configuration.Backends[frontend.Backend].HealthCheck, globalConfiguration.HealthCheck) if hcOpts != nil { log.Debugf("Setting up backend health check %s", *hcOpts) - backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(*hcOpts) + backendsHealthcheck[entryPointName+frontend.Backend] = healthcheck.NewBackendHealthCheck(*hcOpts) } lb = middlewares.NewEmptyBackendHandler(rr, lb) }