From 26100231310ab3a780173a535dd4f4a99b9984fd Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Wed, 17 May 2017 15:22:44 +0200 Subject: [PATCH] refactor: Deflake and Try package - feat: add CI multiplier - refactor: readability - feat: custom Sleep function - refactor(integration): use custom Sleep - feat: show Try progress - feat(try): try response with status code - refactor(try): use a dedicate package. - refactor(integration): Try everywhere - feat(CI): pass CI env var to Integration Tests. - refactor(acme): increase timeout. - feat(acme): show Traefik logs - refactor(integration): use `http.StatusXXX` - refactor: remove Sleep --- Makefile | 3 +- integration/access_log_test.go | 22 +- integration/acme_test.go | 39 ++-- integration/basic_test.go | 75 ++++-- integration/constraint_test.go | 100 +++++--- integration/consul_catalog_test.go | 43 ++-- integration/consul_test.go | 219 ++++++------------ integration/docker_test.go | 48 ++-- integration/dynamodb_test.go | 27 +-- integration/etcd_test.go | 185 +++++---------- integration/eureka_test.go | 63 +++-- integration/file_test.go | 12 +- .../https/clientca/https_1ca1config.toml | 3 + .../https/clientca/https_2ca1config.toml | 3 + .../https/clientca/https_2ca2config.toml | 3 + integration/fixtures/https/https_sni.toml | 3 + integration/healthcheck_test.go | 80 ++++--- integration/https_test.go | 54 +++-- integration/integration_test.go | 24 +- integration/marathon_test.go | 42 ++-- integration/mesos_test.go | 7 +- integration/try/condition.go | 95 ++++++++ integration/try/try.go | 156 +++++++++++++ integration/utils/traefikCmd_test.go | 8 +- integration/utils/try.go | 50 ---- 25 files changed, 751 insertions(+), 613 deletions(-) create mode 100644 integration/try/condition.go create mode 100644 integration/try/try.go delete mode 100644 integration/utils/try.go diff --git a/Makefile b/Makefile index 3535bc7f6..3034f5bd9 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,8 @@ TRAEFIK_ENVS := \ -e VERBOSE \ -e VERSION \ -e CODENAME \ - -e TESTDIRS + -e TESTDIRS \ + -e CI SRCS = $(shell git ls-files '*.go' | grep -v '^vendor/' | grep -v '^integration/vendor/') diff --git a/integration/access_log_test.go b/integration/access_log_test.go index 3356c5a65..71a55dc3a 100644 --- a/integration/access_log_test.go +++ b/integration/access_log_test.go @@ -12,6 +12,7 @@ import ( "strings" "time" + "github.com/containous/traefik/integration/try" "github.com/go-check/check" shellwords "github.com/mattn/go-shellwords" @@ -31,10 +32,17 @@ func (s *AccessLogSuite) TestAccessLog(c *check.C) { err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() + defer os.Remove("access.log") defer os.Remove("traefik.log") - time.Sleep(500 * time.Millisecond) + err = try.Do(1*time.Second, func() error { + if _, err := os.Stat("traefik.log"); err != nil { + return fmt.Errorf("could not get stats for log file: %s", err) + } + return nil + }) + c.Assert(err, checker.IsNil) // Verify Traefik started OK traefikLog, err := ioutil.ReadFile("traefik.log") @@ -53,11 +61,11 @@ func (s *AccessLogSuite) TestAccessLog(c *check.C) { defer ts3.Close() // Make some requests - _, err = http.Get("http://127.0.0.1:8000/test1") + err = try.GetRequest("http://127.0.0.1:8000/test1", 500*time.Millisecond) c.Assert(err, checker.IsNil) - _, err = http.Get("http://127.0.0.1:8000/test2") + err = try.GetRequest("http://127.0.0.1:8000/test2", 500*time.Millisecond) c.Assert(err, checker.IsNil) - _, err = http.Get("http://127.0.0.1:8000/test2") + err = try.GetRequest("http://127.0.0.1:8000/test2", 500*time.Millisecond) c.Assert(err, checker.IsNil) // Verify access.log output as expected @@ -71,14 +79,14 @@ func (s *AccessLogSuite) TestAccessLog(c *check.C) { tokens, err := shellwords.Parse(line) c.Assert(err, checker.IsNil) c.Assert(len(tokens), checker.Equals, 13) - c.Assert(tokens[6], checker.Equals, "200") + c.Assert(regexp.MustCompile(`^\d{3}$`).MatchString(tokens[6]), checker.True) c.Assert(tokens[9], checker.Equals, fmt.Sprintf("%d", i+1)) c.Assert(strings.HasPrefix(tokens[10], "frontend"), checker.True) c.Assert(strings.HasPrefix(tokens[11], "http://127.0.0.1:808"), checker.True) - c.Assert(regexp.MustCompile("^\\d+ms$").MatchString(tokens[12]), checker.True) + c.Assert(regexp.MustCompile(`^\d+ms$`).MatchString(tokens[12]), checker.True) } } - c.Assert(count, checker.Equals, 3) + c.Assert(count, checker.GreaterOrEqualThan, 3) // Verify no other Traefik problems traefikLog, err = ioutil.ReadFile("traefik.log") diff --git a/integration/acme_test.go b/integration/acme_test.go index 485e42673..0d4c02dc8 100644 --- a/integration/acme_test.go +++ b/integration/acme_test.go @@ -4,39 +4,27 @@ import ( "crypto/tls" "net/http" "os" - "os/exec" "time" + "github.com/containous/traefik/integration/try" "github.com/go-check/check" - - "errors" - "github.com/containous/traefik/integration/utils" checker "github.com/vdemeester/shakers" ) // ACME test suites (using libcompose) type AcmeSuite struct { BaseSuite + boulderIP string } func (s *AcmeSuite) SetUpSuite(c *check.C) { s.createComposeProject(c, "boulder") s.composeProject.Start(c) - boulderHost := s.composeProject.Container(c, "boulder").NetworkSettings.IPAddress + s.boulderIP = s.composeProject.Container(c, "boulder").NetworkSettings.IPAddress // wait for boulder - err := utils.Try(120*time.Second, func() error { - resp, err := http.Get("http://" + boulderHost + ":4000/directory") - if err != nil { - return err - } - if resp.StatusCode != 200 { - return errors.New("Expected http 200 from boulder") - } - return nil - }) - + err := try.GetRequest("http://"+s.boulderIP+":4000/directory", 120*time.Second, try.StatusCodeIs(http.StatusOK)) c.Assert(err, checker.IsNil) } @@ -48,15 +36,15 @@ func (s *AcmeSuite) TearDownSuite(c *check.C) { } func (s *AcmeSuite) TestRetrieveAcmeCertificate(c *check.C) { - boulderHost := s.composeProject.Container(c, "boulder").NetworkSettings.IPAddress - file := s.adaptFile(c, "fixtures/acme/acme.toml", struct{ BoulderHost string }{boulderHost}) + file := s.adaptFile(c, "fixtures/acme/acme.toml", struct{ BoulderHost string }{s.boulderIP}) defer os.Remove(file) - cmd := exec.Command(traefikBinary, "--configFile="+file) + cmd, output := s.cmdTraefikWithConfigFile(file) + err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - backend := startTestServer("9010", 200) + backend := startTestServer("9010", http.StatusOK) defer backend.Close() tr := &http.Transport{ @@ -65,13 +53,12 @@ func (s *AcmeSuite) TestRetrieveAcmeCertificate(c *check.C) { client := &http.Client{Transport: tr} // wait for traefik (generating acme account take some seconds) - err = utils.Try(30*time.Second, func() error { + err = try.Do(90*time.Second, func() error { _, err := client.Get("https://127.0.0.1:5001") - if err != nil { - return err - } - return nil + return err }) + // TODO: waiting a refactor of integration tests + s.displayTraefikLog(c, output) c.Assert(err, checker.IsNil) tr = &http.Transport{ @@ -88,5 +75,5 @@ func (s *AcmeSuite) TestRetrieveAcmeCertificate(c *check.C) { resp, err := client.Do(req) c.Assert(err, checker.IsNil) // Expected a 200 - c.Assert(resp.StatusCode, checker.Equals, 200) + c.Assert(resp.StatusCode, checker.Equals, http.StatusOK) } diff --git a/integration/basic_test.go b/integration/basic_test.go index 6f54659b6..a818faac5 100644 --- a/integration/basic_test.go +++ b/integration/basic_test.go @@ -1,13 +1,15 @@ package main import ( + "bytes" + "fmt" "net/http" "os/exec" + "strings" "time" + "github.com/containous/traefik/integration/try" "github.com/go-check/check" - - "bytes" checker "github.com/vdemeester/shakers" ) @@ -21,41 +23,45 @@ func (s *SimpleSuite) TestInvalidConfigShouldFail(c *check.C) { cmd.Stdout = &b cmd.Stderr = &b - cmd.Start() - time.Sleep(500 * time.Millisecond) + err := cmd.Start() + c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - output := b.Bytes() - c.Assert(string(output), checker.Contains, "Near line 0 (last key parsed ''): bare keys cannot contain '{'") + err = try.Do(500*time.Millisecond, func() error { + expected := "Near line 0 (last key parsed ''): bare keys cannot contain '{'" + actual := b.String() + + if !strings.Contains(actual, expected) { + return fmt.Errorf("Got %s, wanted %s", actual, expected) + } + + return nil + }) + c.Assert(err, checker.IsNil) } func (s *SimpleSuite) TestSimpleDefaultConfig(c *check.C) { cmd := exec.Command(traefikBinary, "--configFile=fixtures/simple_default.toml") + err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - time.Sleep(500 * time.Millisecond) // TODO validate : run on 80 - resp, err := http.Get("http://127.0.0.1:8000/") - // Expected a 404 as we did not configure anything + err = try.GetRequest("http://127.0.0.1:8000/", 1*time.Second, try.StatusCodeIs(http.StatusNotFound)) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 404) } func (s *SimpleSuite) TestWithWebConfig(c *check.C) { cmd := exec.Command(traefikBinary, "--configFile=fixtures/simple_web.toml") + err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - time.Sleep(500 * time.Millisecond) - - resp, err := http.Get("http://127.0.0.1:8080/api") - // Expected a 200 + err = try.GetRequest("http://127.0.0.1:8080/api", 1*time.Second, try.StatusCodeIs(http.StatusOK)) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 200) } func (s *SimpleSuite) TestDefaultEntryPoints(c *check.C) { @@ -65,12 +71,21 @@ func (s *SimpleSuite) TestDefaultEntryPoints(c *check.C) { cmd.Stdout = &b cmd.Stderr = &b - cmd.Start() - time.Sleep(500 * time.Millisecond) + err := cmd.Start() + c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - output := b.Bytes() - c.Assert(string(output), checker.Contains, "\"DefaultEntryPoints\":[\"http\"]") + err = try.Do(500*time.Millisecond, func() error { + expected := "\"DefaultEntryPoints\":[\"http\"]" + actual := b.String() + + if !strings.Contains(actual, expected) { + return fmt.Errorf("Got %s, wanted %s", actual, expected) + } + + return nil + }) + c.Assert(err, checker.IsNil) } func (s *SimpleSuite) TestPrintHelp(c *check.C) { @@ -80,11 +95,23 @@ func (s *SimpleSuite) TestPrintHelp(c *check.C) { cmd.Stdout = &b cmd.Stderr = &b - cmd.Start() - time.Sleep(500 * time.Millisecond) + err := cmd.Start() + c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - output := b.Bytes() - c.Assert(string(output), checker.Not(checker.Contains), "panic:") - c.Assert(string(output), checker.Contains, "Usage:") + err = try.Do(500*time.Millisecond, func() error { + expected := "Usage:" + notExpected := "panic:" + actual := b.String() + + if strings.Contains(actual, notExpected) { + return fmt.Errorf("Got %s", actual) + } + if !strings.Contains(actual, expected) { + return fmt.Errorf("Got %s, wanted %s", actual, expected) + } + + return nil + }) + c.Assert(err, checker.IsNil) } diff --git a/integration/constraint_test.go b/integration/constraint_test.go index 66ad8bbc0..0e4c27710 100644 --- a/integration/constraint_test.go +++ b/integration/constraint_test.go @@ -1,13 +1,14 @@ package main import ( + "fmt" "net/http" "os/exec" "time" + "github.com/containous/traefik/integration/try" "github.com/go-check/check" "github.com/hashicorp/consul/api" - checker "github.com/vdemeester/shakers" ) @@ -35,7 +36,16 @@ func (s *ConstraintSuite) SetUpSuite(c *check.C) { s.consulClient = consulClient // Wait for consul to elect itself leader - time.Sleep(2000 * time.Millisecond) + err = try.Do(3*time.Second, func() error { + leader, err := consulClient.Status().Leader() + + if err != nil || len(leader) == 0 { + return fmt.Errorf("Leader not found. %v", err) + } + + return nil + }) + c.Assert(err, checker.IsNil) } func (s *ConstraintSuite) registerService(name string, address string, port int, tags []string) error { @@ -71,7 +81,12 @@ func (s *ConstraintSuite) deregisterService(name string, address string) error { } func (s *ConstraintSuite) TestMatchConstraintGlobal(c *check.C) { - cmd := exec.Command(traefikBinary, "--consulCatalog", "--consulCatalog.endpoint="+s.consulIP+":8500", "--consulCatalog.domain=consul.localhost", "--configFile=fixtures/consul_catalog/simple.toml", "--constraints=tag==api") + cmd := exec.Command(traefikBinary, + "--consulCatalog", + "--consulCatalog.endpoint="+s.consulIP+":8500", + "--consulCatalog.domain=consul.localhost", + "--configFile=fixtures/consul_catalog/simple.toml", + "--constraints=tag==api") err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() @@ -82,19 +97,21 @@ func (s *ConstraintSuite) TestMatchConstraintGlobal(c *check.C) { c.Assert(err, checker.IsNil, check.Commentf("Error registering service")) defer s.deregisterService("test", nginx.NetworkSettings.IPAddress) - time.Sleep(5000 * time.Millisecond) - client := &http.Client{} - req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil) + req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil) c.Assert(err, checker.IsNil) req.Host = "test.consul.localhost" - resp, err := client.Do(req) + err = try.Request(req, 5*time.Second, try.StatusCodeIs(http.StatusOK)) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 200) } func (s *ConstraintSuite) TestDoesNotMatchConstraintGlobal(c *check.C) { - cmd := exec.Command(traefikBinary, "--consulCatalog", "--consulCatalog.endpoint="+s.consulIP+":8500", "--consulCatalog.domain=consul.localhost", "--configFile=fixtures/consul_catalog/simple.toml", "--constraints=tag==api") + cmd := exec.Command(traefikBinary, + "--consulCatalog", + "--consulCatalog.endpoint="+s.consulIP+":8500", + "--consulCatalog.domain=consul.localhost", + "--configFile=fixtures/consul_catalog/simple.toml", + "--constraints=tag==api") err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() @@ -105,19 +122,21 @@ func (s *ConstraintSuite) TestDoesNotMatchConstraintGlobal(c *check.C) { c.Assert(err, checker.IsNil, check.Commentf("Error registering service")) defer s.deregisterService("test", nginx.NetworkSettings.IPAddress) - time.Sleep(5000 * time.Millisecond) - client := &http.Client{} - req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil) + req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil) c.Assert(err, checker.IsNil) req.Host = "test.consul.localhost" - resp, err := client.Do(req) + err = try.Request(req, 5*time.Second, try.StatusCodeIs(http.StatusNotFound)) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 404) } func (s *ConstraintSuite) TestMatchConstraintProvider(c *check.C) { - cmd := exec.Command(traefikBinary, "--consulCatalog", "--consulCatalog.endpoint="+s.consulIP+":8500", "--consulCatalog.domain=consul.localhost", "--configFile=fixtures/consul_catalog/simple.toml", "--consulCatalog.constraints=tag==api") + cmd := exec.Command(traefikBinary, + "--consulCatalog", + "--consulCatalog.endpoint="+s.consulIP+":8500", + "--consulCatalog.domain=consul.localhost", + "--configFile=fixtures/consul_catalog/simple.toml", + "--consulCatalog.constraints=tag==api") err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() @@ -128,19 +147,21 @@ func (s *ConstraintSuite) TestMatchConstraintProvider(c *check.C) { c.Assert(err, checker.IsNil, check.Commentf("Error registering service")) defer s.deregisterService("test", nginx.NetworkSettings.IPAddress) - time.Sleep(5000 * time.Millisecond) - client := &http.Client{} - req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil) + req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil) c.Assert(err, checker.IsNil) req.Host = "test.consul.localhost" - resp, err := client.Do(req) + err = try.Request(req, 5*time.Second, try.StatusCodeIs(http.StatusOK)) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 200) } func (s *ConstraintSuite) TestDoesNotMatchConstraintProvider(c *check.C) { - cmd := exec.Command(traefikBinary, "--consulCatalog", "--consulCatalog.endpoint="+s.consulIP+":8500", "--consulCatalog.domain=consul.localhost", "--configFile=fixtures/consul_catalog/simple.toml", "--consulCatalog.constraints=tag==api") + cmd := exec.Command(traefikBinary, + "--consulCatalog", + "--consulCatalog.endpoint="+s.consulIP+":8500", + "--consulCatalog.domain=consul.localhost", + "--configFile=fixtures/consul_catalog/simple.toml", + "--consulCatalog.constraints=tag==api") err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() @@ -151,19 +172,22 @@ func (s *ConstraintSuite) TestDoesNotMatchConstraintProvider(c *check.C) { c.Assert(err, checker.IsNil, check.Commentf("Error registering service")) defer s.deregisterService("test", nginx.NetworkSettings.IPAddress) - time.Sleep(5000 * time.Millisecond) - client := &http.Client{} - req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil) + req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil) c.Assert(err, checker.IsNil) req.Host = "test.consul.localhost" - resp, err := client.Do(req) + err = try.Request(req, 5*time.Second, try.StatusCodeIs(http.StatusNotFound)) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 404) } func (s *ConstraintSuite) TestMatchMultipleConstraint(c *check.C) { - cmd := exec.Command(traefikBinary, "--consulCatalog", "--consulCatalog.endpoint="+s.consulIP+":8500", "--consulCatalog.domain=consul.localhost", "--configFile=fixtures/consul_catalog/simple.toml", "--consulCatalog.constraints=tag==api", "--constraints=tag!=us-*") + cmd := exec.Command(traefikBinary, + "--consulCatalog", + "--consulCatalog.endpoint="+s.consulIP+":8500", + "--consulCatalog.domain=consul.localhost", + "--configFile=fixtures/consul_catalog/simple.toml", + "--consulCatalog.constraints=tag==api", + "--constraints=tag!=us-*") err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() @@ -174,19 +198,22 @@ func (s *ConstraintSuite) TestMatchMultipleConstraint(c *check.C) { c.Assert(err, checker.IsNil, check.Commentf("Error registering service")) defer s.deregisterService("test", nginx.NetworkSettings.IPAddress) - time.Sleep(5000 * time.Millisecond) - client := &http.Client{} - req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil) + req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil) c.Assert(err, checker.IsNil) req.Host = "test.consul.localhost" - resp, err := client.Do(req) + err = try.Request(req, 5*time.Second, try.StatusCodeIs(http.StatusOK)) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 200) } func (s *ConstraintSuite) TestDoesNotMatchMultipleConstraint(c *check.C) { - cmd := exec.Command(traefikBinary, "--consulCatalog", "--consulCatalog.endpoint="+s.consulIP+":8500", "--consulCatalog.domain=consul.localhost", "--configFile=fixtures/consul_catalog/simple.toml", "--consulCatalog.constraints=tag==api", "--constraints=tag!=us-*") + cmd := exec.Command(traefikBinary, + "--consulCatalog", + "--consulCatalog.endpoint="+s.consulIP+":8500", + "--consulCatalog.domain=consul.localhost", + "--configFile=fixtures/consul_catalog/simple.toml", + "--consulCatalog.constraints=tag==api", + "--constraints=tag!=us-*") err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() @@ -197,13 +224,10 @@ func (s *ConstraintSuite) TestDoesNotMatchMultipleConstraint(c *check.C) { c.Assert(err, checker.IsNil, check.Commentf("Error registering service")) defer s.deregisterService("test", nginx.NetworkSettings.IPAddress) - time.Sleep(5000 * time.Millisecond) - client := &http.Client{} - req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil) + req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil) c.Assert(err, checker.IsNil) req.Host = "test.consul.localhost" - resp, err := client.Do(req) + err = try.Request(req, 5*time.Second, try.StatusCodeIs(http.StatusNotFound)) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 404) } diff --git a/integration/consul_catalog_test.go b/integration/consul_catalog_test.go index 333596da2..62b2413e6 100644 --- a/integration/consul_catalog_test.go +++ b/integration/consul_catalog_test.go @@ -1,14 +1,14 @@ package main import ( - "io/ioutil" + "fmt" "net/http" "os/exec" "time" + "github.com/containous/traefik/integration/try" "github.com/go-check/check" "github.com/hashicorp/consul/api" - checker "github.com/vdemeester/shakers" ) @@ -31,12 +31,21 @@ func (s *ConsulCatalogSuite) SetUpSuite(c *check.C) { config.Address = s.consulIP + ":8500" consulClient, err := api.NewClient(config) if err != nil { - c.Fatalf("Error creating consul client") + c.Fatalf("Error creating consul client. %v", err) } s.consulClient = consulClient // Wait for consul to elect itself leader - time.Sleep(2000 * time.Millisecond) + err = try.Do(3*time.Second, func() error { + leader, err := consulClient.Status().Leader() + + if err != nil || len(leader) == 0 { + return fmt.Errorf("Leader not found. %v", err) + } + + return nil + }) + c.Assert(err, checker.IsNil) } func (s *ConsulCatalogSuite) registerService(name string, address string, port int, tags []string) error { @@ -72,22 +81,26 @@ func (s *ConsulCatalogSuite) deregisterService(name string, address string) erro } func (s *ConsulCatalogSuite) TestSimpleConfiguration(c *check.C) { - cmd := exec.Command(traefikBinary, "--consulCatalog", "--consulCatalog.endpoint="+s.consulIP+":8500", "--configFile=fixtures/consul_catalog/simple.toml") + cmd := exec.Command(traefikBinary, + "--consulCatalog", + "--consulCatalog.endpoint="+s.consulIP+":8500", + "--configFile=fixtures/consul_catalog/simple.toml") err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - time.Sleep(500 * time.Millisecond) // TODO validate : run on 80 - resp, err := http.Get("http://127.0.0.1:8000/") - // Expected a 404 as we did not configure anything + err = try.GetRequest("http://127.0.0.1:8000/", 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound)) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 404) } func (s *ConsulCatalogSuite) TestSingleService(c *check.C) { - cmd := exec.Command(traefikBinary, "--consulCatalog", "--consulCatalog.endpoint="+s.consulIP+":8500", "--consulCatalog.domain=consul.localhost", "--configFile=fixtures/consul_catalog/simple.toml") + cmd := exec.Command(traefikBinary, + "--consulCatalog", + "--consulCatalog.endpoint="+s.consulIP+":8500", + "--consulCatalog.domain=consul.localhost", + "--configFile=fixtures/consul_catalog/simple.toml") err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() @@ -98,16 +111,10 @@ func (s *ConsulCatalogSuite) TestSingleService(c *check.C) { c.Assert(err, checker.IsNil, check.Commentf("Error registering service")) defer s.deregisterService("test", nginx.NetworkSettings.IPAddress) - time.Sleep(5000 * time.Millisecond) - client := &http.Client{} - req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil) + req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil) c.Assert(err, checker.IsNil) req.Host = "test.consul.localhost" - resp, err := client.Do(req) - c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 200) - - _, err = ioutil.ReadAll(resp.Body) + err = try.Request(req, 5*time.Second, try.StatusCodeIs(http.StatusOK), try.HasBody()) c.Assert(err, checker.IsNil) } diff --git a/integration/consul_test.go b/integration/consul_test.go index 61d691bcd..934652e84 100644 --- a/integration/consul_test.go +++ b/integration/consul_test.go @@ -2,18 +2,16 @@ package main import ( "context" - "errors" - "io/ioutil" + "fmt" "net/http" "os" "os/exec" - "strings" "sync" "time" "github.com/containous/staert" "github.com/containous/traefik/cluster" - "github.com/containous/traefik/integration/utils" + "github.com/containous/traefik/integration/try" "github.com/containous/traefik/provider" "github.com/docker/libkv" "github.com/docker/libkv/store" @@ -46,13 +44,7 @@ func (s *ConsulSuite) setupConsul(c *check.C) { s.kv = kv // wait for consul - err = utils.Try(60*time.Second, func() error { - _, err := kv.Exists("test") - if err != nil { - return err - } - return nil - }) + err = try.Do(60*time.Second, try.KVExists(kv, "test")) c.Assert(err, checker.IsNil) } @@ -85,13 +77,7 @@ func (s *ConsulSuite) setupConsulTLS(c *check.C) { s.kv = kv // wait for consul - err = utils.Try(60*time.Second, func() error { - _, err := kv.Exists("test") - if err != nil { - return err - } - return nil - }) + err = try.Do(60*time.Second, try.KVExists(kv, "test")) c.Assert(err, checker.IsNil) } @@ -109,17 +95,15 @@ func (s *ConsulSuite) TestSimpleConfiguration(c *check.C) { consulHost := s.composeProject.Container(c, "consul").NetworkSettings.IPAddress file := s.adaptFile(c, "fixtures/consul/simple.toml", struct{ ConsulHost string }{consulHost}) defer os.Remove(file) + cmd := exec.Command(traefikBinary, "--configFile="+file) err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - time.Sleep(500 * time.Millisecond) - resp, err := http.Get("http://127.0.0.1:8000/") - // Expected a 404 as we did not configure anything + err = try.GetRequest("http://127.0.0.1:8000/", 1*time.Second, try.StatusCodeIs(http.StatusNotFound)) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 404) } func (s *ConsulSuite) TestNominalConfiguration(c *check.C) { @@ -127,28 +111,29 @@ func (s *ConsulSuite) TestNominalConfiguration(c *check.C) { consulHost := s.composeProject.Container(c, "consul").NetworkSettings.IPAddress file := s.adaptFile(c, "fixtures/consul/simple.toml", struct{ ConsulHost string }{consulHost}) defer os.Remove(file) + cmd := exec.Command(traefikBinary, "--configFile="+file) err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - whoami1 := s.composeProject.Container(c, "whoami1") - whoami2 := s.composeProject.Container(c, "whoami2") - whoami3 := s.composeProject.Container(c, "whoami3") - whoami4 := s.composeProject.Container(c, "whoami4") + whoami1IP := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + whoami2IP := s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress + whoami3IP := s.composeProject.Container(c, "whoami3").NetworkSettings.IPAddress + whoami4IP := s.composeProject.Container(c, "whoami4").NetworkSettings.IPAddress backend1 := map[string]string{ "traefik/backends/backend1/circuitbreaker/expression": "NetworkErrorRatio() > 0.5", - "traefik/backends/backend1/servers/server1/url": "http://" + whoami1.NetworkSettings.IPAddress + ":80", + "traefik/backends/backend1/servers/server1/url": "http://" + whoami1IP + ":80", "traefik/backends/backend1/servers/server1/weight": "10", - "traefik/backends/backend1/servers/server2/url": "http://" + whoami2.NetworkSettings.IPAddress + ":80", + "traefik/backends/backend1/servers/server2/url": "http://" + whoami2IP + ":80", "traefik/backends/backend1/servers/server2/weight": "1", } backend2 := map[string]string{ "traefik/backends/backend2/loadbalancer/method": "drr", - "traefik/backends/backend2/servers/server1/url": "http://" + whoami3.NetworkSettings.IPAddress + ":80", + "traefik/backends/backend2/servers/server1/url": "http://" + whoami3IP + ":80", "traefik/backends/backend2/servers/server1/weight": "1", - "traefik/backends/backend2/servers/server2/url": "http://" + whoami4.NetworkSettings.IPAddress + ":80", + "traefik/backends/backend2/servers/server2/url": "http://" + whoami4IP + ":80", "traefik/backends/backend2/servers/server2/weight": "2", } frontend1 := map[string]string{ @@ -181,68 +166,38 @@ func (s *ConsulSuite) TestNominalConfiguration(c *check.C) { } // wait for consul - err = utils.Try(60*time.Second, func() error { - _, err := s.kv.Exists("traefik/frontends/frontend2/routes/test_2/rule") - if err != nil { - return err - } - return nil - }) + err = try.Do(60*time.Second, try.KVExists(s.kv, "traefik/frontends/frontend2/routes/test_2/rule")) c.Assert(err, checker.IsNil) // wait for traefik - err = utils.TryRequest("http://127.0.0.1:8081/api/providers", 60*time.Second, func(res *http.Response) error { - body, err := ioutil.ReadAll(res.Body) - if err != nil { - return err - } - if !strings.Contains(string(body), "Path:/test") { - return errors.New("Incorrect traefik config") - } - return nil - }) + err = try.GetRequest("http://127.0.0.1:8081/api/providers", 60*time.Second, try.BodyContains("Path:/test")) c.Assert(err, checker.IsNil) - client := &http.Client{} - req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil) + req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil) c.Assert(err, checker.IsNil) req.Host = "test.localhost" - response, err := client.Do(req) + err = try.Request(req, 500*time.Millisecond, + try.StatusCodeIs(200), + try.BodyContainsOr(whoami3IP, whoami4IP)) c.Assert(err, checker.IsNil) - c.Assert(response.StatusCode, checker.Equals, 200) - body, err := ioutil.ReadAll(response.Body) + req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/test", nil) c.Assert(err, checker.IsNil) - if !strings.Contains(string(body), whoami3.NetworkSettings.IPAddress) && - !strings.Contains(string(body), whoami4.NetworkSettings.IPAddress) { - c.Fail() - } - req, err = http.NewRequest("GET", "http://127.0.0.1:8000/test", nil) + err = try.Request(req, 500*time.Millisecond, + try.StatusCodeIs(200), + try.BodyContainsOr(whoami1IP, whoami2IP)) c.Assert(err, checker.IsNil) - response, err = client.Do(req) + req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/test2", nil) + try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound)) c.Assert(err, checker.IsNil) - c.Assert(response.StatusCode, checker.Equals, 200) - body, err = ioutil.ReadAll(response.Body) - c.Assert(err, checker.IsNil) - if !strings.Contains(string(body), whoami1.NetworkSettings.IPAddress) && - !strings.Contains(string(body), whoami2.NetworkSettings.IPAddress) { - c.Fail() - } - - req, err = http.NewRequest("GET", "http://127.0.0.1:8000/test2", nil) - resp, err := client.Do(req) - c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 404) - - req, err = http.NewRequest("GET", "http://127.0.0.1:8000/", nil) + req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil) req.Host = "test2.localhost" - resp, err = client.Do(req) + try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound)) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 404) } func (s *ConsulSuite) TestGlobalConfiguration(c *check.C) { @@ -252,41 +207,33 @@ func (s *ConsulSuite) TestGlobalConfiguration(c *check.C) { c.Assert(err, checker.IsNil) // wait for consul - err = utils.Try(60*time.Second, func() error { - _, err := s.kv.Exists("traefik/entrypoints/http/address") - if err != nil { - return err - } - return nil - }) + err = try.Do(60*time.Second, try.KVExists(s.kv, "traefik/entrypoints/http/address")) c.Assert(err, checker.IsNil) // start traefik cmd := exec.Command(traefikBinary, "--configFile=fixtures/simple_web.toml", "--consul", "--consul.endpoint="+consulHost+":8500") - // cmd.Stdout = os.Stdout - // cmd.Stderr = os.Stderr err = cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - whoami1 := s.composeProject.Container(c, "whoami1") - whoami2 := s.composeProject.Container(c, "whoami2") - whoami3 := s.composeProject.Container(c, "whoami3") - whoami4 := s.composeProject.Container(c, "whoami4") + whoami1IP := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + whoami2IP := s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress + whoami3IP := s.composeProject.Container(c, "whoami3").NetworkSettings.IPAddress + whoami4IP := s.composeProject.Container(c, "whoami4").NetworkSettings.IPAddress backend1 := map[string]string{ "traefik/backends/backend1/circuitbreaker/expression": "NetworkErrorRatio() > 0.5", - "traefik/backends/backend1/servers/server1/url": "http://" + whoami1.NetworkSettings.IPAddress + ":80", + "traefik/backends/backend1/servers/server1/url": "http://" + whoami1IP + ":80", "traefik/backends/backend1/servers/server1/weight": "10", - "traefik/backends/backend1/servers/server2/url": "http://" + whoami2.NetworkSettings.IPAddress + ":80", + "traefik/backends/backend1/servers/server2/url": "http://" + whoami2IP + ":80", "traefik/backends/backend1/servers/server2/weight": "1", } backend2 := map[string]string{ "traefik/backends/backend2/loadbalancer/method": "drr", - "traefik/backends/backend2/servers/server1/url": "http://" + whoami3.NetworkSettings.IPAddress + ":80", + "traefik/backends/backend2/servers/server1/url": "http://" + whoami3IP + ":80", "traefik/backends/backend2/servers/server1/weight": "1", - "traefik/backends/backend2/servers/server2/url": "http://" + whoami4.NetworkSettings.IPAddress + ":80", + "traefik/backends/backend2/servers/server2/url": "http://" + whoami4IP + ":80", "traefik/backends/backend2/servers/server2/weight": "2", } frontend1 := map[string]string{ @@ -319,37 +266,20 @@ func (s *ConsulSuite) TestGlobalConfiguration(c *check.C) { } // wait for consul - err = utils.Try(60*time.Second, func() error { - _, err := s.kv.Exists("traefik/frontends/frontend2/routes/test_2/rule") - if err != nil { - return err - } - return nil - }) + err = try.Do(60*time.Second, try.KVExists(s.kv, "traefik/frontends/frontend2/routes/test_2/rule")) c.Assert(err, checker.IsNil) // wait for traefik - err = utils.TryRequest("http://127.0.0.1:8080/api/providers", 60*time.Second, func(res *http.Response) error { - body, err := ioutil.ReadAll(res.Body) - if err != nil { - return err - } - if !strings.Contains(string(body), "Path:/test") { - return errors.New("Incorrect traefik config") - } - return nil - }) + err = try.GetRequest("http://127.0.0.1:8080/api/providers", 60*time.Second, try.BodyContains("Path:/test")) c.Assert(err, checker.IsNil) //check - client := &http.Client{} - req, err := http.NewRequest("GET", "http://127.0.0.1:8001/", nil) + req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8001/", nil) c.Assert(err, checker.IsNil) req.Host = "test.localhost" - response, err := client.Do(req) + err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK)) c.Assert(err, checker.IsNil) - c.Assert(response.StatusCode, checker.Equals, 200) } func (s *ConsulSuite) skipTestGlobalConfigurationWithClientTLS(c *check.C) { @@ -361,13 +291,7 @@ func (s *ConsulSuite) skipTestGlobalConfigurationWithClientTLS(c *check.C) { c.Assert(err, checker.IsNil) // wait for consul - err = utils.Try(60*time.Second, func() error { - _, err := s.kv.Exists("traefik/web/address") - if err != nil { - return err - } - return nil - }) + err = try.Do(60*time.Second, try.KVExists(s.kv, "traefik/web/address")) c.Assert(err, checker.IsNil) // start traefik @@ -377,29 +301,24 @@ func (s *ConsulSuite) skipTestGlobalConfigurationWithClientTLS(c *check.C) { "--consul.tls.cert=resources/tls/consul.cert", "--consul.tls.key=resources/tls/consul.key", "--consul.tls.insecureskipverify") - // cmd.Stdout = os.Stdout - // cmd.Stderr = os.Stderr err = cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() // wait for traefik - err = utils.TryRequest("http://127.0.0.1:8081/api/providers", 60*time.Second, func(res *http.Response) error { - _, err := ioutil.ReadAll(res.Body) - if err != nil { - return err - } - return nil - }) + err = try.GetRequest("http://127.0.0.1:8081/api/providers", 60*time.Second) c.Assert(err, checker.IsNil) - } + func (s *ConsulSuite) TestCommandStoreConfig(c *check.C) { s.setupConsul(c) consulHost := s.composeProject.Container(c, "consul").NetworkSettings.IPAddress - cmd := exec.Command(traefikBinary, "storeconfig", "--configFile=fixtures/simple_web.toml", "--consul.endpoint="+consulHost+":8500") + cmd := exec.Command(traefikBinary, + "storeconfig", + "--configFile=fixtures/simple_web.toml", + "--consul.endpoint="+consulHost+":8500") err := cmd.Start() c.Assert(err, checker.IsNil) @@ -412,22 +331,18 @@ func (s *ConsulSuite) TestCommandStoreConfig(c *check.C) { "/traefik/defaultentrypoints/0": "http", "/traefik/entrypoints/http/address": ":8000", "/traefik/web/address": ":8080", - "/traefik/consul/endpoint": (consulHost + ":8500"), + "/traefik/consul/endpoint": consulHost + ":8500", } for key, value := range checkmap { var p *store.KVPair - err = utils.Try(60*time.Second, func() error { + err = try.Do(60*time.Second, func() error { p, err = s.kv.Get(key) - if err != nil { - return err - } - return nil + return err }) c.Assert(err, checker.IsNil) c.Assert(string(p.Value), checker.Equals, value) - } } @@ -457,12 +372,12 @@ func (s *ConsulSuite) TestDatastore(c *check.C) { Int: 1, }) c.Assert(err, checker.IsNil) - time.Sleep(2 * time.Second) - test1 := datastore1.Get().(*TestStruct) - c.Assert(test1.String, checker.Equals, "foo") - test2 := datastore2.Get().(*TestStruct) - c.Assert(test2.String, checker.Equals, "foo") + err = try.Do(3*time.Second, datastoreContains(datastore1, "foo")) + c.Assert(err, checker.IsNil) + + err = try.Do(3*time.Second, datastoreContains(datastore2, "foo")) + c.Assert(err, checker.IsNil) setter2, _, err := datastore2.Begin() c.Assert(err, checker.IsNil) @@ -471,12 +386,12 @@ func (s *ConsulSuite) TestDatastore(c *check.C) { Int: 2, }) c.Assert(err, checker.IsNil) - time.Sleep(2 * time.Second) - test1 = datastore1.Get().(*TestStruct) - c.Assert(test1.String, checker.Equals, "bar") - test2 = datastore2.Get().(*TestStruct) - c.Assert(test2.String, checker.Equals, "bar") + err = try.Do(3*time.Second, datastoreContains(datastore1, "bar")) + c.Assert(err, checker.IsNil) + + err = try.Do(3*time.Second, datastoreContains(datastore2, "bar")) + c.Assert(err, checker.IsNil) wg := &sync.WaitGroup{} wg.Add(4) @@ -520,3 +435,13 @@ func (s *ConsulSuite) TestDatastore(c *check.C) { }() wg.Wait() } + +func datastoreContains(datastore *cluster.Datastore, expectedValue string) func() error { + return func() error { + kvStruct := datastore.Get().(*TestStruct) + if kvStruct.String != expectedValue { + return fmt.Errorf("Got %s, wanted %s", kvStruct.String, expectedValue) + } + return nil + } +} diff --git a/integration/docker_test.go b/integration/docker_test.go index 4aa6f0b7b..e221676dc 100644 --- a/integration/docker_test.go +++ b/integration/docker_test.go @@ -10,6 +10,7 @@ import ( "strings" "time" + "github.com/containous/traefik/integration/try" "github.com/docker/docker/pkg/namesgenerator" "github.com/go-check/check" @@ -84,13 +85,10 @@ func (s *DockerSuite) TestSimpleConfiguration(c *check.C) { c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - time.Sleep(500 * time.Millisecond) // TODO validate : run on 80 - resp, err := http.Get("http://127.0.0.1:8000/") - - c.Assert(err, checker.IsNil) // Expected a 404 as we did not comfigure anything - c.Assert(resp.StatusCode, checker.Equals, 404) + err = try.GetRequest("http://127.0.0.1:8000/", 500*time.Millisecond, try.StatusCodeIs(404)) + c.Assert(err, checker.IsNil) } func (s *DockerSuite) TestDefaultDockerContainers(c *check.C) { @@ -104,17 +102,13 @@ func (s *DockerSuite) TestDefaultDockerContainers(c *check.C) { c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - // FIXME Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?) - time.Sleep(1500 * time.Millisecond) - - client := &http.Client{} - req, err := http.NewRequest("GET", "http://127.0.0.1:8000/version", nil) + req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil) c.Assert(err, checker.IsNil) req.Host = fmt.Sprintf("%s.docker.localhost", strings.Replace(name, "_", "-", -1)) - resp, err := client.Do(req) + // FIXME Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?) + resp, err := try.ResponseUntilStatusCode(req, 1500*time.Millisecond, 200) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 200) body, err := ioutil.ReadAll(resp.Body) c.Assert(err, checker.IsNil) @@ -140,17 +134,13 @@ func (s *DockerSuite) TestDockerContainersWithLabels(c *check.C) { c.Assert(err, checker.IsNil) defer cmd.Process.Kill() + req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil) + c.Assert(err, checker.IsNil) + req.Host = "my.super.host" + // FIXME Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?) - time.Sleep(1500 * time.Millisecond) - - client := &http.Client{} - req, err := http.NewRequest("GET", "http://127.0.0.1:8000/version", nil) + resp, err := try.ResponseUntilStatusCode(req, 1500*time.Millisecond, http.StatusOK) c.Assert(err, checker.IsNil) - req.Host = fmt.Sprintf("my.super.host") - resp, err := client.Do(req) - - c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 200) body, err := ioutil.ReadAll(resp.Body) c.Assert(err, checker.IsNil) @@ -176,15 +166,13 @@ func (s *DockerSuite) TestDockerContainersWithOneMissingLabels(c *check.C) { c.Assert(err, checker.IsNil) defer cmd.Process.Kill() + req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil) + c.Assert(err, checker.IsNil) + req.Host = "my.super.host" + // FIXME Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?) - time.Sleep(1500 * time.Millisecond) - - client := &http.Client{} - req, err := http.NewRequest("GET", "http://127.0.0.1:8000/version", nil) + // TODO validate : run on 80 + // Expected a 404 as we did not comfigure anything + err = try.Request(req, 1500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound)) c.Assert(err, checker.IsNil) - req.Host = fmt.Sprintf("my.super.host") - resp, err := client.Do(req) - - c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 404) } diff --git a/integration/dynamodb_test.go b/integration/dynamodb_test.go index 9dceed66e..5e7cbf16f 100644 --- a/integration/dynamodb_test.go +++ b/integration/dynamodb_test.go @@ -1,12 +1,9 @@ package main import ( - "errors" - "io/ioutil" "net/http" "os" "os/exec" - "strings" "time" "github.com/aws/aws-sdk-go/aws" @@ -14,7 +11,7 @@ import ( "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/dynamodb" "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" - "github.com/containous/traefik/integration/utils" + "github.com/containous/traefik/integration/try" "github.com/containous/traefik/types" "github.com/go-check/check" checker "github.com/vdemeester/shakers" @@ -49,7 +46,7 @@ func (s *DynamoDBSuite) SetUpSuite(c *check.C) { Endpoint: aws.String(dynamoURL), } var sess *session.Session - err := utils.Try(60*time.Second, func() error { + err := try.Do(60*time.Second, func() error { _, err := session.NewSession(config) if err != nil { return err @@ -154,24 +151,16 @@ func (s *DynamoDBSuite) TestSimpleConfiguration(c *check.C) { err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - err = utils.TryRequest("http://127.0.0.1:8081/api/providers", 120*time.Second, func(res *http.Response) error { - body, err := ioutil.ReadAll(res.Body) - if err != nil { - return err - } - if !strings.Contains(string(body), "Host:test.traefik.io") { - return errors.New("incorrect traefik config") - } - return nil - }) + + err = try.GetRequest("http://127.0.0.1:8081/api/providers", 120*time.Second, try.BodyContains("Host:test.traefik.io")) c.Assert(err, checker.IsNil) - client := &http.Client{} - req, err := http.NewRequest("GET", "http://127.0.0.1:8080", nil) + + req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080", nil) c.Assert(err, checker.IsNil) req.Host = "test.traefik.io" - response, err := client.Do(req) + + err = try.Request(req, 200*time.Millisecond, try.StatusCodeIs(http.StatusOK)) c.Assert(err, checker.IsNil) - c.Assert(response.StatusCode, checker.Equals, 200) } func (s *DynamoDBSuite) TearDownSuite(c *check.C) { diff --git a/integration/etcd_test.go b/integration/etcd_test.go index 092619669..7b5c529a4 100644 --- a/integration/etcd_test.go +++ b/integration/etcd_test.go @@ -1,23 +1,21 @@ package main import ( - "github.com/go-check/check" + "crypto/tls" + "io/ioutil" "net/http" + "os" "os/exec" + "strings" "time" - checker "github.com/vdemeester/shakers" - - "crypto/tls" - "errors" - "fmt" - "github.com/containous/traefik/integration/utils" + "github.com/containous/traefik/integration/try" "github.com/docker/libkv" "github.com/docker/libkv/store" "github.com/docker/libkv/store/etcd" - "io/ioutil" - "os" - "strings" + "github.com/go-check/check" + + checker "github.com/vdemeester/shakers" ) // Etcd test suites (using libcompose) @@ -45,12 +43,9 @@ func (s *EtcdSuite) SetUpTest(c *check.C) { s.kv = kv // wait for etcd - err = utils.Try(60*time.Second, func() error { + err = try.Do(60*time.Second, func() error { _, err := kv.Exists("test") - if err != nil { - return fmt.Errorf("Etcd connection error to %s: %v", url, err) - } - return nil + return err }) c.Assert(err, checker.IsNil) } @@ -73,13 +68,10 @@ func (s *EtcdSuite) TestSimpleConfiguration(c *check.C) { c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - time.Sleep(1000 * time.Millisecond) // TODO validate : run on 80 - resp, err := http.Get("http://127.0.0.1:8000/") - // Expected a 404 as we did not configure anything + err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound)) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 404) } func (s *EtcdSuite) TestNominalConfiguration(c *check.C) { @@ -91,23 +83,23 @@ func (s *EtcdSuite) TestNominalConfiguration(c *check.C) { c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - whoami1 := s.composeProject.Container(c, "whoami1") - whoami2 := s.composeProject.Container(c, "whoami2") - whoami3 := s.composeProject.Container(c, "whoami3") - whoami4 := s.composeProject.Container(c, "whoami4") + whoami1IP := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + whoami2IP := s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress + whoami3IP := s.composeProject.Container(c, "whoami3").NetworkSettings.IPAddress + whoami4IP := s.composeProject.Container(c, "whoami4").NetworkSettings.IPAddress backend1 := map[string]string{ "/traefik/backends/backend1/circuitbreaker/expression": "NetworkErrorRatio() > 0.5", - "/traefik/backends/backend1/servers/server1/url": "http://" + whoami1.NetworkSettings.IPAddress + ":80", + "/traefik/backends/backend1/servers/server1/url": "http://" + whoami1IP + ":80", "/traefik/backends/backend1/servers/server1/weight": "10", - "/traefik/backends/backend1/servers/server2/url": "http://" + whoami2.NetworkSettings.IPAddress + ":80", + "/traefik/backends/backend1/servers/server2/url": "http://" + whoami2IP + ":80", "/traefik/backends/backend1/servers/server2/weight": "1", } backend2 := map[string]string{ "/traefik/backends/backend2/loadbalancer/method": "drr", - "/traefik/backends/backend2/servers/server1/url": "http://" + whoami3.NetworkSettings.IPAddress + ":80", + "/traefik/backends/backend2/servers/server1/url": "http://" + whoami3IP + ":80", "/traefik/backends/backend2/servers/server1/weight": "1", - "/traefik/backends/backend2/servers/server2/url": "http://" + whoami4.NetworkSettings.IPAddress + ":80", + "/traefik/backends/backend2/servers/server2/url": "http://" + whoami4IP + ":80", "/traefik/backends/backend2/servers/server2/weight": "2", } frontend1 := map[string]string{ @@ -140,68 +132,55 @@ func (s *EtcdSuite) TestNominalConfiguration(c *check.C) { } // wait for etcd - err = utils.Try(60*time.Second, func() error { + err = try.Do(60*time.Second, func() error { _, err := s.kv.Exists("/traefik/frontends/frontend2/routes/test_2/rule") - if err != nil { - return err - } - return nil + return err }) c.Assert(err, checker.IsNil) // wait for traefik - err = utils.TryRequest("http://127.0.0.1:8081/api/providers", 60*time.Second, func(res *http.Response) error { - body, err := ioutil.ReadAll(res.Body) - if err != nil { - return err - } - if !strings.Contains(string(body), "Path:/test") { - return errors.New("Incorrect traefik config") - } - return nil - }) + err = try.GetRequest("http://127.0.0.1:8081/api/providers", 60*time.Second, try.BodyContains("Path:/test")) c.Assert(err, checker.IsNil) client := &http.Client{} - req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil) + req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil) c.Assert(err, checker.IsNil) req.Host = "test.localhost" response, err := client.Do(req) c.Assert(err, checker.IsNil) - c.Assert(response.StatusCode, checker.Equals, 200) + c.Assert(response.StatusCode, checker.Equals, http.StatusOK) body, err := ioutil.ReadAll(response.Body) c.Assert(err, checker.IsNil) - if !strings.Contains(string(body), whoami3.NetworkSettings.IPAddress) && - !strings.Contains(string(body), whoami4.NetworkSettings.IPAddress) { + if !strings.Contains(string(body), whoami3IP) && + !strings.Contains(string(body), whoami4IP) { c.Fail() } - req, err = http.NewRequest("GET", "http://127.0.0.1:8000/test", nil) + req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/test", nil) c.Assert(err, checker.IsNil) response, err = client.Do(req) c.Assert(err, checker.IsNil) - c.Assert(response.StatusCode, checker.Equals, 200) + c.Assert(response.StatusCode, checker.Equals, http.StatusOK) body, err = ioutil.ReadAll(response.Body) c.Assert(err, checker.IsNil) - if !strings.Contains(string(body), whoami1.NetworkSettings.IPAddress) && - !strings.Contains(string(body), whoami2.NetworkSettings.IPAddress) { + if !strings.Contains(string(body), whoami1IP) && + !strings.Contains(string(body), whoami2IP) { c.Fail() } - req, err = http.NewRequest("GET", "http://127.0.0.1:8000/test2", nil) + req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/test2", nil) req.Host = "test2.localhost" resp, err := client.Do(req) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 404) + c.Assert(resp.StatusCode, checker.Equals, http.StatusNotFound) - req, err = http.NewRequest("GET", "http://127.0.0.1:8000/", nil) - resp, err = client.Do(req) + resp, err = http.Get("http://127.0.0.1:8000/") c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 404) + c.Assert(resp.StatusCode, checker.Equals, http.StatusNotFound) } func (s *EtcdSuite) TestGlobalConfiguration(c *check.C) { @@ -210,41 +189,36 @@ func (s *EtcdSuite) TestGlobalConfiguration(c *check.C) { c.Assert(err, checker.IsNil) // wait for etcd - err = utils.Try(60*time.Second, func() error { + err = try.Do(60*time.Second, func() error { _, err := s.kv.Exists("/traefik/entrypoints/http/address") - if err != nil { - return err - } - return nil + return err }) c.Assert(err, checker.IsNil) // start traefik cmd := exec.Command(traefikBinary, "--configFile=fixtures/simple_web.toml", "--etcd", "--etcd.endpoint="+etcdHost+":4001") - // cmd.Stdout = os.Stdout - // cmd.Stderr = os.Stderr err = cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - whoami1 := s.composeProject.Container(c, "whoami1") - whoami2 := s.composeProject.Container(c, "whoami2") - whoami3 := s.composeProject.Container(c, "whoami3") - whoami4 := s.composeProject.Container(c, "whoami4") + whoami1IP := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + whoami2IP := s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress + whoami3IP := s.composeProject.Container(c, "whoami3").NetworkSettings.IPAddress + whoami4IP := s.composeProject.Container(c, "whoami4").NetworkSettings.IPAddress backend1 := map[string]string{ "/traefik/backends/backend1/circuitbreaker/expression": "NetworkErrorRatio() > 0.5", - "/traefik/backends/backend1/servers/server1/url": "http://" + whoami1.NetworkSettings.IPAddress + ":80", + "/traefik/backends/backend1/servers/server1/url": "http://" + whoami1IP + ":80", "/traefik/backends/backend1/servers/server1/weight": "10", - "/traefik/backends/backend1/servers/server2/url": "http://" + whoami2.NetworkSettings.IPAddress + ":80", + "/traefik/backends/backend1/servers/server2/url": "http://" + whoami2IP + ":80", "/traefik/backends/backend1/servers/server2/weight": "1", } backend2 := map[string]string{ "/traefik/backends/backend2/loadbalancer/method": "drr", - "/traefik/backends/backend2/servers/server1/url": "http://" + whoami3.NetworkSettings.IPAddress + ":80", + "/traefik/backends/backend2/servers/server1/url": "http://" + whoami3IP + ":80", "/traefik/backends/backend2/servers/server1/weight": "1", - "/traefik/backends/backend2/servers/server2/url": "http://" + whoami4.NetworkSettings.IPAddress + ":80", + "/traefik/backends/backend2/servers/server2/url": "http://" + whoami4IP + ":80", "/traefik/backends/backend2/servers/server2/weight": "2", } frontend1 := map[string]string{ @@ -277,50 +251,34 @@ func (s *EtcdSuite) TestGlobalConfiguration(c *check.C) { } // wait for etcd - err = utils.Try(60*time.Second, func() error { + err = try.Do(60*time.Second, func() error { _, err := s.kv.Exists("/traefik/frontends/frontend2/routes/test_2/rule") - if err != nil { - return err - } - return nil + return err }) c.Assert(err, checker.IsNil) // wait for traefik - err = utils.TryRequest("http://127.0.0.1:8080/api/providers", 60*time.Second, func(res *http.Response) error { - body, err := ioutil.ReadAll(res.Body) - if err != nil { - return err - } - if !strings.Contains(string(body), "Path:/test") { - return errors.New("Incorrect traefik config") - } - return nil - }) + err = try.GetRequest("http://127.0.0.1:8080/api/providers", 60*time.Second, try.BodyContains("Path:/test")) c.Assert(err, checker.IsNil) //check - client := &http.Client{} - req, err := http.NewRequest("GET", "http://127.0.0.1:8001/", nil) + req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8001/", nil) c.Assert(err, checker.IsNil) req.Host = "test.localhost" - response, err := client.Do(req) + err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK)) c.Assert(err, checker.IsNil) - c.Assert(response.StatusCode, checker.Equals, 200) } func (s *EtcdSuite) TestCertificatesContentstWithSNIConfigHandshake(c *check.C) { etcdHost := s.composeProject.Container(c, "etcd").NetworkSettings.IPAddress // start traefik cmd := exec.Command(traefikBinary, "--configFile=fixtures/simple_web.toml", "--etcd", "--etcd.endpoint="+etcdHost+":4001") - // cmd.Stdout = os.Stdout - // cmd.Stderr = os.Stderr - whoami1 := s.composeProject.Container(c, "whoami1") - whoami2 := s.composeProject.Container(c, "whoami2") - whoami3 := s.composeProject.Container(c, "whoami3") - whoami4 := s.composeProject.Container(c, "whoami4") + whoami1IP := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + whoami2IP := s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress + whoami3IP := s.composeProject.Container(c, "whoami3").NetworkSettings.IPAddress + whoami4IP := s.composeProject.Container(c, "whoami4").NetworkSettings.IPAddress //Copy the contents of the certificate files into ETCD snitestComCert, err := ioutil.ReadFile("fixtures/https/snitest.com.cert") @@ -343,16 +301,16 @@ func (s *EtcdSuite) TestCertificatesContentstWithSNIConfigHandshake(c *check.C) backend1 := map[string]string{ "/traefik/backends/backend1/circuitbreaker/expression": "NetworkErrorRatio() > 0.5", - "/traefik/backends/backend1/servers/server1/url": "http://" + whoami1.NetworkSettings.IPAddress + ":80", + "/traefik/backends/backend1/servers/server1/url": "http://" + whoami1IP + ":80", "/traefik/backends/backend1/servers/server1/weight": "10", - "/traefik/backends/backend1/servers/server2/url": "http://" + whoami2.NetworkSettings.IPAddress + ":80", + "/traefik/backends/backend1/servers/server2/url": "http://" + whoami2IP + ":80", "/traefik/backends/backend1/servers/server2/weight": "1", } backend2 := map[string]string{ "/traefik/backends/backend2/loadbalancer/method": "drr", - "/traefik/backends/backend2/servers/server1/url": "http://" + whoami3.NetworkSettings.IPAddress + ":80", + "/traefik/backends/backend2/servers/server1/url": "http://" + whoami3IP + ":80", "/traefik/backends/backend2/servers/server1/weight": "1", - "/traefik/backends/backend2/servers/server2/url": "http://" + whoami4.NetworkSettings.IPAddress + ":80", + "/traefik/backends/backend2/servers/server2/url": "http://" + whoami4IP + ":80", "/traefik/backends/backend2/servers/server2/weight": "2", } frontend1 := map[string]string{ @@ -389,13 +347,7 @@ func (s *EtcdSuite) TestCertificatesContentstWithSNIConfigHandshake(c *check.C) } // wait for etcd - err = utils.Try(60*time.Second, func() error { - _, err := s.kv.Exists("/traefik/frontends/frontend2/routes/test_2/rule") - if err != nil { - return err - } - return nil - }) + err = try.Do(60*time.Second, try.KVExists(s.kv, "/traefik/frontends/frontend2/routes/test_2/rule")) c.Assert(err, checker.IsNil) err = cmd.Start() @@ -403,16 +355,7 @@ func (s *EtcdSuite) TestCertificatesContentstWithSNIConfigHandshake(c *check.C) defer cmd.Process.Kill() // wait for traefik - err = utils.TryRequest("http://127.0.0.1:8080/api/providers", 60*time.Second, func(res *http.Response) error { - body, err := ioutil.ReadAll(res.Body) - if err != nil { - return err - } - if !strings.Contains(string(body), "Host:snitest.org") { - return errors.New("Incorrect traefik config") - } - return nil - }) + err = try.GetRequest("http://127.0.0.1:8080/api/providers", 60*time.Second, try.BodyContains("Host:snitest.org")) c.Assert(err, checker.IsNil) //check @@ -448,21 +391,17 @@ func (s *EtcdSuite) TestCommandStoreConfig(c *check.C) { "/traefik/defaultentrypoints/0": "http", "/traefik/entrypoints/http/address": ":8000", "/traefik/web/address": ":8080", - "/traefik/etcd/endpoint": (etcdHost + ":4001"), + "/traefik/etcd/endpoint": etcdHost + ":4001", } for key, value := range checkmap { var p *store.KVPair - err = utils.Try(60*time.Second, func() error { + err = try.Do(60*time.Second, func() error { p, err = s.kv.Get(key) - if err != nil { - return err - } - return nil + return err }) c.Assert(err, checker.IsNil) c.Assert(string(p.Value), checker.Equals, value) - } } diff --git a/integration/eureka_test.go b/integration/eureka_test.go index 9ae354441..832ccca7a 100644 --- a/integration/eureka_test.go +++ b/integration/eureka_test.go @@ -2,8 +2,6 @@ package main import ( "bytes" - "errors" - "io/ioutil" "net/http" "os" "os/exec" @@ -11,44 +9,43 @@ import ( "text/template" "time" - "github.com/containous/traefik/integration/utils" + "github.com/containous/traefik/integration/try" "github.com/go-check/check" checker "github.com/vdemeester/shakers" ) // Eureka test suites (using libcompose) -type EurekaSuite struct{ BaseSuite } +type EurekaSuite struct { + BaseSuite + eurekaIP string + eurekaURL string +} func (s *EurekaSuite) SetUpSuite(c *check.C) { s.createComposeProject(c, "eureka") s.composeProject.Start(c) + eureka := s.composeProject.Container(c, "eureka") + s.eurekaIP = eureka.NetworkSettings.IPAddress + s.eurekaURL = "http://" + s.eurekaIP + ":8761/eureka/apps" + + // wait for eureka + err := try.GetRequest(s.eurekaURL, 60*time.Second) + c.Assert(err, checker.IsNil) } func (s *EurekaSuite) TestSimpleConfiguration(c *check.C) { - eurekaHost := s.composeProject.Container(c, "eureka").NetworkSettings.IPAddress whoami1Host := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress - file := s.adaptFile(c, "fixtures/eureka/simple.toml", struct{ EurekaHost string }{eurekaHost}) + file := s.adaptFile(c, "fixtures/eureka/simple.toml", struct{ EurekaHost string }{s.eurekaIP}) defer os.Remove(file) cmd := exec.Command(traefikBinary, "--configFile="+file) err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - eurekaURL := "http://" + eurekaHost + ":8761/eureka/apps" - - // wait for eureka - err = utils.TryRequest(eurekaURL, 60*time.Second, func(res *http.Response) error { - if err != nil { - return err - } - return nil - }) - c.Assert(err, checker.IsNil) - eurekaTemplate := ` { "instance": { @@ -66,7 +63,7 @@ func (s *EurekaSuite) TestSimpleConfiguration(c *check.C) { } }` - tmpl, err := template.New("eurekaTemlate").Parse(eurekaTemplate) + tmpl, err := template.New("eurekaTemplate").Parse(eurekaTemplate) c.Assert(err, checker.IsNil) buf := new(bytes.Buffer) templateVars := map[string]string{ @@ -76,36 +73,28 @@ func (s *EurekaSuite) TestSimpleConfiguration(c *check.C) { } // add in eureka err = tmpl.Execute(buf, templateVars) - resp, err := http.Post(eurekaURL+"/tests-integration-traefik", "application/json", strings.NewReader(buf.String())) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 204) + + req, err := http.NewRequest(http.MethodPost, s.eurekaURL+"/tests-integration-traefik", strings.NewReader(buf.String())) + c.Assert(err, checker.IsNil) + req.Header.Set("Content-Type", "application/json") + + err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusNoContent)) + c.Assert(err, checker.IsNil) // wait for traefik - err = utils.TryRequest("http://127.0.0.1:8080/api/providers", 60*time.Second, func(res *http.Response) error { - body, err := ioutil.ReadAll(res.Body) - if err != nil { - return err - } - if !strings.Contains(string(body), "Host:tests-integration-traefik") { - return errors.New("Incorrect traefik config") - } - return nil - }) + err = try.GetRequest("http://127.0.0.1:8080/api/providers", 60*time.Second, try.BodyContains("Host:tests-integration-traefik")) c.Assert(err, checker.IsNil) - client := &http.Client{} - req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil) + req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil) c.Assert(err, checker.IsNil) req.Host = "tests-integration-traefik" - resp, err = client.Do(req) + err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK)) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 200) // TODO validate : run on 80 - resp, err = http.Get("http://127.0.0.1:8000/") - // Expected a 404 as we did not configure anything + err = try.GetRequest("http://127.0.0.1:8000/", 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound)) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 404) } diff --git a/integration/file_test.go b/integration/file_test.go index 25a1dde9e..6397bde72 100644 --- a/integration/file_test.go +++ b/integration/file_test.go @@ -5,8 +5,8 @@ import ( "os/exec" "time" + "github.com/containous/traefik/integration/try" "github.com/go-check/check" - checker "github.com/vdemeester/shakers" ) @@ -25,12 +25,9 @@ func (s *FileSuite) TestSimpleConfiguration(c *check.C) { c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - time.Sleep(1000 * time.Millisecond) - resp, err := http.Get("http://127.0.0.1:8000/") - // Expected a 404 as we did not configure anything + try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound)) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 404) } // #56 regression test, make sure it does not fail @@ -40,10 +37,7 @@ func (s *FileSuite) TestSimpleConfigurationNoPanic(c *check.C) { c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - time.Sleep(1000 * time.Millisecond) - resp, err := http.Get("http://127.0.0.1:8000/") - // Expected a 404 as we did not configure anything + try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound)) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 404) } diff --git a/integration/fixtures/https/clientca/https_1ca1config.toml b/integration/fixtures/https/clientca/https_1ca1config.toml index e4130cab6..a25c0c75b 100644 --- a/integration/fixtures/https/clientca/https_1ca1config.toml +++ b/integration/fixtures/https/clientca/https_1ca1config.toml @@ -14,6 +14,9 @@ defaultEntryPoints = ["https"] CertFile = "fixtures/https/snitest.org.cert" KeyFile = "fixtures/https/snitest.org.key" +[web] + address = ":8080" + [file] [backends] diff --git a/integration/fixtures/https/clientca/https_2ca1config.toml b/integration/fixtures/https/clientca/https_2ca1config.toml index 09de989e0..9211cf8dd 100644 --- a/integration/fixtures/https/clientca/https_2ca1config.toml +++ b/integration/fixtures/https/clientca/https_2ca1config.toml @@ -14,6 +14,9 @@ defaultEntryPoints = ["https"] CertFile = "fixtures/https/snitest.org.cert" KeyFile = "fixtures/https/snitest.org.key" +[web] + address = ":8080" + [file] [backends] diff --git a/integration/fixtures/https/clientca/https_2ca2config.toml b/integration/fixtures/https/clientca/https_2ca2config.toml index fa6bcbf75..2eec0a82a 100644 --- a/integration/fixtures/https/clientca/https_2ca2config.toml +++ b/integration/fixtures/https/clientca/https_2ca2config.toml @@ -14,6 +14,9 @@ defaultEntryPoints = ["https"] CertFile = "fixtures/https/snitest.org.cert" KeyFile = "fixtures/https/snitest.org.key" +[web] + address = ":8080" + [file] [backends] diff --git a/integration/fixtures/https/https_sni.toml b/integration/fixtures/https/https_sni.toml index 66f737a36..c88febc7c 100644 --- a/integration/fixtures/https/https_sni.toml +++ b/integration/fixtures/https/https_sni.toml @@ -13,6 +13,9 @@ defaultEntryPoints = ["https"] CertFile = "fixtures/https/snitest.org.cert" KeyFile = "fixtures/https/snitest.org.key" +[web] + address = ":8080" + [file] [backends] diff --git a/integration/healthcheck_test.go b/integration/healthcheck_test.go index bef35f0d4..4336f5c12 100644 --- a/integration/healthcheck_test.go +++ b/integration/healthcheck_test.go @@ -2,17 +2,13 @@ package main import ( "bytes" - "errors" - "io/ioutil" "net/http" "os" "os/exec" - "strings" "time" - "github.com/containous/traefik/integration/utils" + "github.com/containous/traefik/integration/try" "github.com/go-check/check" - checker "github.com/vdemeester/shakers" ) @@ -22,7 +18,6 @@ type HealthCheckSuite struct{ BaseSuite } func (s *HealthCheckSuite) SetUpSuite(c *check.C) { s.createComposeProject(c, "healthcheck") s.composeProject.Start(c) - } func (s *HealthCheckSuite) TestSimpleConfiguration(c *check.C) { @@ -42,50 +37,59 @@ func (s *HealthCheckSuite) TestSimpleConfiguration(c *check.C) { defer cmd.Process.Kill() // wait for traefik - err = utils.TryRequest("http://127.0.0.1:8080/api/providers", 60*time.Second, func(res *http.Response) error { - body, err := ioutil.ReadAll(res.Body) - if err != nil { - return err - } - if !strings.Contains(string(body), "Host:test.localhost") { - return errors.New("Incorrect traefik config: " + string(body)) - } - return nil - }) + err = try.GetRequest("http://127.0.0.1:8080/api/providers", 60*time.Second, try.BodyContains("Host:test.localhost")) c.Assert(err, checker.IsNil) + 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) + + // Fix all whoami health to 500 client := &http.Client{} - req, err := http.NewRequest("GET", "http://127.0.0.1:8000/health", nil) - c.Assert(err, checker.IsNil) - req.Host = "test.localhost" + whoamiHosts := []string{whoami1Host, whoami2Host} + for _, whoami := range whoamiHosts { + statusInternalServerErrorReq, err := http.NewRequest(http.MethodPost, "http://"+whoami+"/health", bytes.NewBuffer([]byte("500"))) + c.Assert(err, checker.IsNil) + _, err = client.Do(statusInternalServerErrorReq) + c.Assert(err, checker.IsNil) + } - resp, err := client.Do(req) - c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 200) + // Waiting for Traefik healthcheck + try.Sleep(2 * time.Second) - resp, err = client.Do(req) - c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 200) - - healthReq, err := http.NewRequest("POST", "http://"+whoami1Host+"/health", bytes.NewBuffer([]byte("500"))) - c.Assert(err, checker.IsNil) - _, err = client.Do(healthReq) + // Verify frontend health : 500 + err = try.Request(frontendHealthReq, 3*time.Second, try.StatusCodeIs(http.StatusInternalServerError)) c.Assert(err, checker.IsNil) - time.Sleep(time.Second * 3) - - resp, err = client.Do(req) + // Change one whoami health to 200 + statusOKReq1, err := http.NewRequest(http.MethodPost, "http://"+whoami1Host+"/health", bytes.NewBuffer([]byte("200"))) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 200) - - resp, err = client.Do(req) + _, err = client.Do(statusOKReq1) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 200) + + // Verify frontend health : after + err = try.Request(frontendHealthReq, 3*time.Second, try.StatusCodeIs(http.StatusOK)) + c.Assert(err, checker.IsNil) + + frontendReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil) + c.Assert(err, checker.IsNil) + frontendReq.Host = "test.localhost" + + // Check if whoami1 respond + err = try.Request(frontendReq, 500*time.Millisecond, try.BodyContains(whoami1Host)) + 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)) + c.Assert(err, checker.Not(checker.IsNil)) // TODO validate : run on 80 - resp, err = http.Get("http://127.0.0.1:8000/") + resp, err := http.Get("http://127.0.0.1:8000/") // Expected a 404 as we did not configure anything c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 404) + c.Assert(resp.StatusCode, checker.Equals, http.StatusNotFound) } diff --git a/integration/https_test.go b/integration/https_test.go index 7bf2c2a59..ec4a02846 100644 --- a/integration/https_test.go +++ b/integration/https_test.go @@ -5,11 +5,10 @@ import ( "net" "net/http" "net/http/httptest" - "os/exec" "time" + "github.com/containous/traefik/integration/try" "github.com/go-check/check" - checker "github.com/vdemeester/shakers" ) @@ -20,12 +19,14 @@ type HTTPSSuite struct{ BaseSuite } // "snitest.com", which happens to match the CN of 'snitest.com.crt'. The test // verifies that traefik presents the correct certificate. func (s *HTTPSSuite) TestWithSNIConfigHandshake(c *check.C) { - cmd := exec.Command(traefikBinary, "--configFile=fixtures/https/https_sni.toml") + cmd, _ := s.cmdTraefikWithConfigFile("fixtures/https/https_sni.toml") err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - time.Sleep(500 * time.Millisecond) + // wait for Traefik + err = try.GetRequest("http://127.0.0.1:8080/api/providers", 500*time.Millisecond, try.BodyContains("Host:snitest.org")) + c.Assert(err, checker.IsNil) tlsConfig := &tls.Config{ InsecureSkipVerify: true, @@ -51,17 +52,24 @@ func (s *HTTPSSuite) TestWithSNIConfigHandshake(c *check.C) { // SNI hostnames of "snitest.org" and "snitest.com". The test verifies // that traefik routes the requests to the expected backends. func (s *HTTPSSuite) TestWithSNIConfigRoute(c *check.C) { - cmd := exec.Command(traefikBinary, "--configFile=fixtures/https/https_sni.toml") + cmd, _ := s.cmdTraefikWithConfigFile("fixtures/https/https_sni.toml") err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - backend1 := startTestServer("9010", 204) - backend2 := startTestServer("9020", 205) + // wait for Traefik + err = try.GetRequest("http://127.0.0.1:8080/api/providers", 500*time.Millisecond, try.BodyContains("Host:snitest.org")) + c.Assert(err, checker.IsNil) + + backend1 := startTestServer("9010", http.StatusNoContent) + backend2 := startTestServer("9020", http.StatusResetContent) defer backend1.Close() defer backend2.Close() - time.Sleep(2000 * time.Millisecond) + err = try.GetRequest(backend1.URL, 1*time.Second, try.StatusCodeIs(http.StatusNoContent)) + c.Assert(err, checker.IsNil) + err = try.GetRequest(backend2.URL, 1*time.Second, try.StatusCodeIs(http.StatusResetContent)) + c.Assert(err, checker.IsNil) tr1 := &http.Transport{ TLSClientConfig: &tls.Config{ @@ -77,35 +85,39 @@ func (s *HTTPSSuite) TestWithSNIConfigRoute(c *check.C) { } client := &http.Client{Transport: tr1} - req, _ := http.NewRequest("GET", "https://127.0.0.1:4443/", nil) + req, err := http.NewRequest(http.MethodGet, "https://127.0.0.1:4443/", nil) + c.Assert(err, checker.IsNil) req.Host = "snitest.com" req.Header.Set("Host", "snitest.com") req.Header.Set("Accept", "*/*") resp, err := client.Do(req) c.Assert(err, checker.IsNil) // Expected a 204 (from backend1) - c.Assert(resp.StatusCode, checker.Equals, 204) + c.Assert(resp.StatusCode, checker.Equals, http.StatusNoContent) client = &http.Client{Transport: tr2} - req, _ = http.NewRequest("GET", "https://127.0.0.1:4443/", nil) + req, err = http.NewRequest(http.MethodGet, "https://127.0.0.1:4443/", nil) + c.Assert(err, checker.IsNil) req.Host = "snitest.org" req.Header.Set("Host", "snitest.org") req.Header.Set("Accept", "*/*") resp, err = client.Do(req) c.Assert(err, checker.IsNil) // Expected a 205 (from backend2) - c.Assert(resp.StatusCode, checker.Equals, 205) + c.Assert(resp.StatusCode, checker.Equals, http.StatusResetContent) } // TestWithClientCertificateAuthentication // The client has to send a certificate signed by a CA trusted by the server func (s *HTTPSSuite) TestWithClientCertificateAuthentication(c *check.C) { - cmd := exec.Command(traefikBinary, "--configFile=fixtures/https/clientca/https_1ca1config.toml") + cmd, _ := s.cmdTraefikWithConfigFile("fixtures/https/clientca/https_1ca1config.toml") err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - time.Sleep(500 * time.Millisecond) + // wait for Traefik + err = try.GetRequest("http://127.0.0.1:8080/api/providers", 500*time.Millisecond, try.BodyContains("Host:snitest.org")) + c.Assert(err, checker.IsNil) tlsConfig := &tls.Config{ InsecureSkipVerify: true, @@ -144,12 +156,14 @@ func (s *HTTPSSuite) TestWithClientCertificateAuthentication(c *check.C) { // TestWithClientCertificateAuthentication // Use two CA:s and test that clients with client signed by either of them can connect func (s *HTTPSSuite) TestWithClientCertificateAuthenticationMultipeCAs(c *check.C) { - cmd := exec.Command(traefikBinary, "--configFile=fixtures/https/clientca/https_2ca1config.toml") + cmd, _ := s.cmdTraefikWithConfigFile("fixtures/https/clientca/https_2ca1config.toml") err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - time.Sleep(500 * time.Millisecond) + // wait for Traefik + err = try.GetRequest("http://127.0.0.1:8080/api/providers", 500*time.Millisecond, try.BodyContains("Host:snitest.org")) + c.Assert(err, checker.IsNil) tlsConfig := &tls.Config{ InsecureSkipVerify: true, @@ -201,12 +215,14 @@ func (s *HTTPSSuite) TestWithClientCertificateAuthenticationMultipeCAs(c *check. // TestWithClientCertificateAuthentication // Use two CA:s in two different files and test that clients with client signed by either of them can connect func (s *HTTPSSuite) TestWithClientCertificateAuthenticationMultipeCAsMultipleFiles(c *check.C) { - cmd := exec.Command(traefikBinary, "--configFile=fixtures/https/clientca/https_2ca2config.toml") + cmd, _ := s.cmdTraefikWithConfigFile("fixtures/https/clientca/https_2ca2config.toml") err := cmd.Start() c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - time.Sleep(500 * time.Millisecond) + // wait for Traefik + err = try.GetRequest("http://127.0.0.1:8080/api/providers", 1000*time.Millisecond, try.BodyContains("Host:snitest.org")) + c.Assert(err, checker.IsNil) tlsConfig := &tls.Config{ InsecureSkipVerify: true, @@ -269,5 +285,5 @@ func startTestServer(port string, statusCode int) (ts *httptest.Server) { Config: &http.Server{Handler: handler}, } ts.Start() - return + return ts } diff --git a/integration/integration_test.go b/integration/integration_test.go index d0d24c212..d39bb53c4 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -2,6 +2,7 @@ package main import ( + "bytes" "fmt" "io/ioutil" "net" @@ -13,7 +14,6 @@ import ( "github.com/containous/traefik/integration/utils" "github.com/go-check/check" - compose "github.com/libkermit/compose/check" checker "github.com/vdemeester/shakers" ) @@ -71,12 +71,34 @@ func (s *BaseSuite) createComposeProject(c *check.C, name string) { s.composeProject = compose.CreateProject(c, projectName, composeFile) } +// Deprecated: unused func (s *BaseSuite) traefikCmd(c *check.C, args ...string) (*exec.Cmd, string) { cmd, out, err := utils.RunCommand(traefikBinary, args...) c.Assert(err, checker.IsNil, check.Commentf("Fail to run %s with %v", traefikBinary, args)) return cmd, out } +func (s *BaseSuite) cmdTraefikWithConfigFile(file string) (*exec.Cmd, *bytes.Buffer) { + return s.cmdTraefik("--configFile=" + file) +} + +func (s *BaseSuite) cmdTraefik(args ...string) (*exec.Cmd, *bytes.Buffer) { + cmd := exec.Command(traefikBinary, args...) + var out bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &out + return cmd, &out +} + +func (s *BaseSuite) displayTraefikLog(c *check.C, output *bytes.Buffer) { + if output == nil || output.Len() == 0 { + fmt.Printf("%s: No Traefik logs present.", c.TestName()) + } else { + fmt.Printf("%s: Traefik logs: ", c.TestName()) + fmt.Println(output.String()) + } +} + func (s *BaseSuite) adaptFileForHost(c *check.C, path string) string { dockerHost := os.Getenv("DOCKER_HOST") if dockerHost == "" { diff --git a/integration/marathon_test.go b/integration/marathon_test.go index e029794f6..857d6812a 100644 --- a/integration/marathon_test.go +++ b/integration/marathon_test.go @@ -5,8 +5,8 @@ import ( "os/exec" "time" + "github.com/containous/traefik/integration/try" "github.com/go-check/check" - checker "github.com/vdemeester/shakers" ) @@ -16,18 +16,28 @@ type MarathonSuite struct{ BaseSuite } func (s *MarathonSuite) SetUpSuite(c *check.C) { s.createComposeProject(c, "marathon") s.composeProject.Start(c) - // wait for marathon - // err := utils.TryRequest("http://127.0.0.1:8080/ping", 60*time.Second, func(res *http.Response) error { - // body, err := ioutil.ReadAll(res.Body) - // if err != nil { - // return err - // } - // if !strings.Contains(string(body), "ping") { - // return errors.New("Incorrect marathon config") - // } - // return nil - // }) - // c.Assert(err, checker.IsNil) + + // FIXME Doesn't work... + //// "github.com/gambol99/go-marathon" + //config := marathon.NewDefaultConfig() + // + //marathonClient, err := marathon.NewClient(config) + //if err != nil { + // c.Fatalf("Error creating Marathon client. %v", err) + //} + // + //// Wait for Marathon to elect itself leader + //err = try.Do(30*time.Second, func() error { + // leader, err := marathonClient.Leader() + // + // if err != nil || len(leader) == 0 { + // return fmt.Errorf("Leader not found. %v", err) + // } + // + // return nil + //}) + // + //c.Assert(err, checker.IsNil) } func (s *MarathonSuite) TestSimpleConfiguration(c *check.C) { @@ -36,11 +46,9 @@ func (s *MarathonSuite) TestSimpleConfiguration(c *check.C) { c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - time.Sleep(500 * time.Millisecond) // TODO validate : run on 80 - resp, err := http.Get("http://127.0.0.1:8000/") - // Expected a 404 as we did not configure anything + err = try.GetRequest("http://127.0.0.1:8000/", 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound)) + c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 404) } diff --git a/integration/mesos_test.go b/integration/mesos_test.go index d8cd1654a..ef2afe3d5 100644 --- a/integration/mesos_test.go +++ b/integration/mesos_test.go @@ -5,8 +5,8 @@ import ( "os/exec" "time" + "github.com/containous/traefik/integration/try" "github.com/go-check/check" - checker "github.com/vdemeester/shakers" ) @@ -23,11 +23,8 @@ func (s *MesosSuite) TestSimpleConfiguration(c *check.C) { c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - time.Sleep(500 * time.Millisecond) // TODO validate : run on 80 - resp, err := http.Get("http://127.0.0.1:8000/") - // Expected a 404 as we did not configure anything + err = try.GetRequest("http://127.0.0.1:8000/", 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound)) c.Assert(err, checker.IsNil) - c.Assert(resp.StatusCode, checker.Equals, 404) } diff --git a/integration/try/condition.go b/integration/try/condition.go new file mode 100644 index 000000000..8737c9bb4 --- /dev/null +++ b/integration/try/condition.go @@ -0,0 +1,95 @@ +package try + +import ( + "errors" + "fmt" + "io/ioutil" + "net/http" + "strings" + + "github.com/docker/libkv/store" +) + +// ResponseCondition is a retry condition function. +// It receives a response, and returns an error +// if the response failed the condition. +type ResponseCondition func(*http.Response) error + +// BodyContains returns a retry condition function. +// The condition returns an error if the request body does not contain all the given +// strings. +func BodyContains(values ...string) ResponseCondition { + return func(res *http.Response) error { + body, err := ioutil.ReadAll(res.Body) + if err != nil { + return fmt.Errorf("failed to read response body: %s", err) + } + + for _, value := range values { + if !strings.Contains(string(body), value) { + return fmt.Errorf("could not find '%s' in body '%s'", value, string(body)) + } + } + return nil + } +} + +// BodyContainsOr returns a retry condition function. +// The condition returns an error if the request body does not contain one of the given +// strings. +func BodyContainsOr(values ...string) ResponseCondition { + return func(res *http.Response) error { + body, err := ioutil.ReadAll(res.Body) + if err != nil { + return fmt.Errorf("failed to read response body: %s", err) + } + + for _, value := range values { + if strings.Contains(string(body), value) { + return nil + } + } + return fmt.Errorf("could not find '%v' in body '%s'", values, string(body)) + } +} + +// HasBody returns a retry condition function. +// The condition returns an error if the request body does not have body content. +func HasBody() ResponseCondition { + return func(res *http.Response) error { + body, err := ioutil.ReadAll(res.Body) + if err != nil { + return fmt.Errorf("failed to read response body: %s", err) + } + + if len(body) == 0 { + return errors.New("Response doesn't have body content") + } + return nil + } +} + +// StatusCodeIs returns a retry condition function. +// The condition returns an error if the given response's status code is not the +// given HTTP status code. +func StatusCodeIs(status int) ResponseCondition { + return func(res *http.Response) error { + if res.StatusCode != status { + return fmt.Errorf("got status code %d, wanted %d", res.StatusCode, status) + } + return nil + } +} + +// DoCondition is a retry condition function. +// It returns an error +type DoCondition func() error + +// KVExists is a retry condition function. +// Verify if a Key exists in the store +func KVExists(kv store.Store, key string) DoCondition { + return func() error { + _, err := kv.Exists(key) + return err + } +} diff --git a/integration/try/try.go b/integration/try/try.go new file mode 100644 index 000000000..f201cd0d8 --- /dev/null +++ b/integration/try/try.go @@ -0,0 +1,156 @@ +package try + +import ( + "fmt" + "math" + "net/http" + "os" + "time" + + "github.com/containous/traefik/log" +) + +const ( + // CITimeoutMultiplier is the multiplier for all timeout in the CI + CITimeoutMultiplier = 3 + maxInterval = 5 * time.Second +) + +type timedAction func(timeout time.Duration, operation DoCondition) error + +// Sleep pauses the current goroutine for at least the duration d. +// Deprecated: Use only when use an other Try[...] functions is not possible. +func Sleep(d time.Duration) { + d = applyCIMultiplier(d) + time.Sleep(d) +} + +// Response is like Request, but returns the response for further +// processing at the call site. +// Conditions are not allowed since it would complicate signaling if the +// response body needs to be closed or not. Callers are expected to close on +// their own if the function returns a nil error. +func Response(req *http.Request, timeout time.Duration) (*http.Response, error) { + return doTryRequest(req, timeout) +} + +// ResponseUntilStatusCode is like Request, but returns the response for further +// processing at the call site. +// Conditions are not allowed since it would complicate signaling if the +// response body needs to be closed or not. Callers are expected to close on +// their own if the function returns a nil error. +func ResponseUntilStatusCode(req *http.Request, timeout time.Duration, statusCode int) (*http.Response, error) { + return doTryRequest(req, timeout, StatusCodeIs(statusCode)) +} + +// GetRequest is like Do, but runs a request against the given URL and applies +// the condition on the response. +// ResponseCondition may be nil, in which case only the request against the URL must +// succeed. +func GetRequest(url string, timeout time.Duration, conditions ...ResponseCondition) error { + resp, err := doTryGet(url, timeout, conditions...) + + if resp != nil && resp.Body != nil { + defer resp.Body.Close() + } + + return err +} + +// Request is like Do, but runs a request against the given URL and applies +// the condition on the response. +// ResponseCondition may be nil, in which case only the request against the URL must +// succeed. +func Request(req *http.Request, timeout time.Duration, conditions ...ResponseCondition) error { + resp, err := doTryRequest(req, timeout, conditions...) + + if resp != nil && resp.Body != nil { + defer resp.Body.Close() + } + + return err +} + +// Do repeatedly executes an operation until no error condition occurs or the +// given timeout is reached, whatever comes first. +func Do(timeout time.Duration, operation DoCondition) error { + if timeout <= 0 { + panic("timeout must be larger than zero") + } + + interval := time.Duration(math.Ceil(float64(timeout) / 15.0)) + if interval > maxInterval { + interval = maxInterval + } + + timeout = applyCIMultiplier(timeout) + + var err error + if err = operation(); err == nil { + fmt.Println("+") + return nil + } + fmt.Print("*") + + stopTimer := time.NewTimer(timeout) + defer stopTimer.Stop() + retryTick := time.NewTicker(interval) + defer retryTick.Stop() + + for { + select { + case <-stopTimer.C: + fmt.Println("-") + return fmt.Errorf("try operation failed: %s", err) + case <-retryTick.C: + fmt.Print("*") + if err = operation(); err == nil { + fmt.Println("+") + return err + } + } + } +} + +func doTryGet(url string, timeout time.Duration, conditions ...ResponseCondition) (*http.Response, error) { + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return nil, err + } + + return doTryRequest(req, timeout, conditions...) +} + +func doTryRequest(request *http.Request, timeout time.Duration, conditions ...ResponseCondition) (*http.Response, error) { + return doRequest(Do, timeout, request, conditions...) +} + +func doRequest(action timedAction, timeout time.Duration, request *http.Request, conditions ...ResponseCondition) (*http.Response, error) { + var resp *http.Response + return resp, action(timeout, func() error { + var err error + client := http.DefaultClient + + resp, err = client.Do(request) + if err != nil { + return err + } + + for _, condition := range conditions { + if err := condition(resp); err != nil { + return err + } + } + + return nil + }) +} + +func applyCIMultiplier(timeout time.Duration) time.Duration { + ci := os.Getenv("CI") + if len(ci) > 0 { + log.Debug("Apply CI multiplier:", CITimeoutMultiplier) + return time.Duration(float64(timeout) * CITimeoutMultiplier) + } + return timeout +} diff --git a/integration/utils/traefikCmd_test.go b/integration/utils/traefikCmd_test.go index 9a5965586..6a9724122 100644 --- a/integration/utils/traefikCmd_test.go +++ b/integration/utils/traefikCmd_test.go @@ -70,15 +70,15 @@ func TestHelperProcess(t *testing.T) { argsStr := strings.Join(args, " ") switch argsStr { case "an exitCode 127": - fmt.Fprintf(os.Stderr, "an error has occurred with exitCode 127") + fmt.Fprint(os.Stderr, "an error has occurred with exitCode 127") os.Exit(127) case "an error": - fmt.Fprintf(os.Stderr, "an error has occurred") + fmt.Fprint(os.Stderr, "an error has occurred") os.Exit(1) case "it works": - fmt.Fprintf(os.Stdout, "it works") + fmt.Fprint(os.Stdout, "it works") default: - fmt.Fprintf(os.Stdout, "no arguments") + fmt.Fprint(os.Stdout, "no arguments") } default: fmt.Fprintf(os.Stderr, "Command %s not found.", cmd) diff --git a/integration/utils/try.go b/integration/utils/try.go deleted file mode 100644 index b353ac5a6..000000000 --- a/integration/utils/try.go +++ /dev/null @@ -1,50 +0,0 @@ -package utils - -import ( - "errors" - "github.com/cenk/backoff" - "net/http" - "strconv" - "time" -) - -// TryRequest try operation timeout, and retry backoff -func TryRequest(url string, timeout time.Duration, condition Condition) error { - exponentialBackOff := backoff.NewExponentialBackOff() - exponentialBackOff.MaxElapsedTime = timeout - var res *http.Response - err := backoff.Retry(func() error { - var err error - res, err = http.Get(url) - if err != nil { - return err - } - return condition(res) - }, exponentialBackOff) - return err -} - -// Try try operation timeout, and retry backoff -func Try(timeout time.Duration, operation func() error) error { - exponentialBackOff := backoff.NewExponentialBackOff() - exponentialBackOff.MaxElapsedTime = timeout - err := backoff.Retry(operation, exponentialBackOff) - return err -} - -// Condition is a retry condition function. -// It receives a response, and returns an error -// if the response failed the condition. -type Condition func(*http.Response) error - -// ErrorIfStatusCodeIsNot returns a retry condition function. -// The condition returns an error -// if the given response's status code is not the given HTTP status code. -func ErrorIfStatusCodeIsNot(status int) Condition { - return func(res *http.Response) error { - if res.StatusCode != status { - return errors.New("Bad status. Got: " + res.Status + ", expected:" + strconv.Itoa(status)) - } - return nil - } -}