test(promtail): Fix flaky test with promtail bind port. (#6859)

* test(promtail): Fix flaky test with promtail bind port.

You cannot run promtail tests if there is already running promtail in your local.
e.g:
```
$ go test -run TestPromtail ./clients/pkg/promtail/
```

It gives you error
```
--- FAIL: TestPromtail (0.02s)
    promtail_test.go:112: error creating promtail listen tcp 127.0.0.1:9080: bind: address already in use
FAIL
FAIL	github.com/grafana/loki/clients/pkg/promtail	0.043s
```
Cause for the error is, test uses static default port (the same we use for promtail normally) in tests.

This is not **too** annonying if seen in isolation. But mainly annoying in two cases particularly
1. Hard to run tests parallely in general with these kind of static ports
2. These are causing some real problems in some integeration tests on GEL which starts docker-compose to run some test suites and
even stopping containers won't release ports soon enough making CI fail randomly.

This PR takes advantage of Go idiom of passing `port=0` to http (and also grpc) servers enforce Go's `net` package to bind some unused random ports. Making each test run choose random ports
enabling easy running theses tests in parallel.

NOTE: This PR also contains upgrade in `common/server` package that made this fix possible.
https://github.com/weaveworks/common/pull/249

Signed-off-by: Kaviraj <kavirajkanagaraj@gmail.com>

* go mod tidy

Signed-off-by: Kaviraj <kavirajkanagaraj@gmail.com>
pull/6865/head
Kaviraj Kanagaraj 4 years ago committed by GitHub
parent e372383f0d
commit e8b44172d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 20
      clients/pkg/promtail/promtail_test.go
  2. 12
      clients/pkg/promtail/server/server.go
  3. 2
      go.mod
  4. 4
      go.sum
  5. 9
      vendor/github.com/weaveworks/common/instrument/instrument.go
  6. 11
      vendor/github.com/weaveworks/common/server/server.go
  7. 2
      vendor/modules.txt

@ -7,6 +7,7 @@ import (
"io/ioutil"
"math"
"math/rand"
"net"
"net/http"
"net/url"
"os"
@ -36,6 +37,7 @@ import (
"github.com/grafana/loki/clients/pkg/promtail/positions"
"github.com/grafana/loki/clients/pkg/promtail/scrapeconfig"
"github.com/grafana/loki/clients/pkg/promtail/server"
pserver "github.com/grafana/loki/clients/pkg/promtail/server"
file2 "github.com/grafana/loki/clients/pkg/promtail/targets/file"
"github.com/grafana/loki/pkg/logproto"
@ -43,8 +45,6 @@ import (
util_log "github.com/grafana/loki/pkg/util/log"
)
const httpTestPort = 9080
var clientMetrics = client.NewMetrics(prometheus.DefaultRegisterer, nil)
func TestPromtail(t *testing.T) {
@ -122,6 +122,10 @@ func TestPromtail(t *testing.T) {
}()
defer p.Shutdown() // In case the test fails before the call to Shutdown below.
svr := p.server.(*pserver.PromtailServer)
httpListenAddr := svr.Server.HTTPListenAddr()
expectedCounts := map[string]int{}
startupMarkerFile := testDir + "/startupMarker.log"
@ -202,7 +206,7 @@ func TestPromtail(t *testing.T) {
<-time.After(500 * time.Millisecond)
// Pull out some prometheus metrics before shutting down
metricsBytes, contentType := getPromMetrics(t)
metricsBytes, contentType := getPromMetrics(t, httpListenAddr)
p.Shutdown()
@ -496,8 +500,8 @@ func (h *testServerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.recMtx.Unlock()
}
func getPromMetrics(t *testing.T) ([]byte, string) {
resp, err := http.Get(fmt.Sprintf("http://localhost:%d/metrics", httpTestPort))
func getPromMetrics(t *testing.T, httpListenAddr net.Addr) ([]byte, string) {
resp, err := http.Get(fmt.Sprintf("http://%s/metrics", httpListenAddr))
if err != nil {
t.Fatal("Could not query metrics endpoint", err)
}
@ -561,7 +565,11 @@ func buildTestConfig(t *testing.T, positionsFileName string, logDirName string)
cfg.ServerConfig.HTTPListenAddress = hostname
cfg.ServerConfig.ExternalURL = hostname
cfg.ServerConfig.GRPCListenAddress = hostname
cfg.ServerConfig.HTTPListenPort = httpTestPort
// NOTE: setting port to `0` makes it bind to some unused random port.
// enabling tests run more self contained and easy to run tests in parallel.
cfg.ServerConfig.HTTPListenPort = 0
cfg.ServerConfig.GRPCListenPort = 0
// Override some of those defaults
cfg.ClientConfig.URL = clientURL

@ -36,7 +36,7 @@ type Server interface {
}
// Server embed weaveworks server with static file and templating capability
type server struct {
type PromtailServer struct {
*serverww.Server
log log.Logger
tms *targets.TargetManagers
@ -88,7 +88,7 @@ func New(cfg Config, log log.Logger, tms *targets.TargetManagers, promtailCfg st
healthCheckTargetFlag = *cfg.HealthCheckTarget
}
serv := &server{
serv := &PromtailServer{
Server: wws,
log: log,
tms: tms,
@ -108,7 +108,7 @@ func New(cfg Config, log log.Logger, tms *targets.TargetManagers, promtailCfg st
}
// serviceDiscovery serves the service discovery page.
func (s *server) serviceDiscovery(rw http.ResponseWriter, req *http.Request) {
func (s *PromtailServer) serviceDiscovery(rw http.ResponseWriter, req *http.Request) {
var index []string
allTarget := s.tms.AllTargets()
for job := range allTarget {
@ -175,7 +175,7 @@ func (s *server) serviceDiscovery(rw http.ResponseWriter, req *http.Request) {
})
}
func (s *server) config(rw http.ResponseWriter, req *http.Request) {
func (s *PromtailServer) config(rw http.ResponseWriter, req *http.Request) {
executeTemplate(req.Context(), rw, templateOptions{
Data: s.promtailCfg,
BuildVersion: version.Info(),
@ -186,7 +186,7 @@ func (s *server) config(rw http.ResponseWriter, req *http.Request) {
}
// targets serves the targets page.
func (s *server) targets(rw http.ResponseWriter, req *http.Request) {
func (s *PromtailServer) targets(rw http.ResponseWriter, req *http.Request) {
executeTemplate(req.Context(), rw, templateOptions{
Data: struct {
TargetPools map[string][]target.Target
@ -219,7 +219,7 @@ func (s *server) targets(rw http.ResponseWriter, req *http.Request) {
}
// ready serves the ready endpoint
func (s *server) ready(rw http.ResponseWriter, _ *http.Request) {
func (s *PromtailServer) ready(rw http.ResponseWriter, _ *http.Request) {
if s.healthCheckTarget && !s.tms.Ready() {
http.Error(rw, readinessProbeFailure, http.StatusInternalServerError)
return

@ -92,7 +92,7 @@ require (
github.com/thanos-io/thanos v0.22.0
github.com/tonistiigi/fifo v0.0.0-20190226154929-a9fb20d87448
github.com/uber/jaeger-client-go v2.30.0+incompatible
github.com/weaveworks/common v0.0.0-20220706100410-67d27ed40fae
github.com/weaveworks/common v0.0.0-20220809154356-72ba250fe659
github.com/xdg-go/scram v1.0.2
go.etcd.io/bbolt v1.3.6
go.uber.org/atomic v1.9.0

@ -1581,8 +1581,8 @@ github.com/vultr/govultr/v2 v2.17.1 h1:UBmotwA0mkGtyJMakUF9jhLH/W3mN5wfGRn543i/B
github.com/vultr/govultr/v2 v2.17.1/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI=
github.com/wavefronthq/wavefront-sdk-go v0.9.2/go.mod h1:hQI6y8M9OtTCtc0xdwh+dCER4osxXdEAeCpacjpDZEU=
github.com/weaveworks/common v0.0.0-20210913144402-035033b78a78/go.mod h1:YU9FvnS7kUnRt6HY10G+2qHkwzP3n3Vb1XsXDsJTSp8=
github.com/weaveworks/common v0.0.0-20220706100410-67d27ed40fae h1:Z8YibUpdBEdCq8nwrYXJQ8vYooevbmEBIdFpseXK3/8=
github.com/weaveworks/common v0.0.0-20220706100410-67d27ed40fae/go.mod h1:YfOOLoW1Q/jIIu0WLeSwgStmrKjuJEZSKTAUc+0KFvE=
github.com/weaveworks/common v0.0.0-20220809154356-72ba250fe659 h1:McPAXT5tVW1NVs7SSGOCU2EzLyiUdygrGKZJZMTYZgA=
github.com/weaveworks/common v0.0.0-20220809154356-72ba250fe659/go.mod h1:YfOOLoW1Q/jIIu0WLeSwgStmrKjuJEZSKTAUc+0KFvE=
github.com/weaveworks/promrus v1.2.0 h1:jOLf6pe6/vss4qGHjXmGz4oDJQA+AOCqEL3FvvZGz7M=
github.com/weaveworks/promrus v1.2.0/go.mod h1:SaE82+OJ91yqjrE1rsvBWVzNZKcHYFtMUyS1+Ogs/KA=
github.com/willf/bitset v1.1.11 h1:N7Z7E9UvjW+sGsEl7k/SJrvY2reP1A07MrGuCjIOjRE=

@ -68,16 +68,9 @@ func (c *HistogramCollector) After(ctx context.Context, method, statusCode strin
// (this will always work for a HistogramVec).
func ObserveWithExemplar(ctx context.Context, histogram prometheus.Observer, seconds float64) {
if traceID, ok := tracing.ExtractSampledTraceID(ctx); ok {
lbls := prometheus.Labels{"traceID": traceID}
if userID, err := user.ExtractUserID(ctx); err == nil {
lbls["user"] = userID
}
if orgID, err := user.ExtractOrgID(ctx); err == nil {
lbls["organization"] = orgID
}
histogram.(prometheus.ExemplarObserver).ObserveWithExemplar(
seconds,
lbls,
prometheus.Labels{"traceID": traceID},
)
return
}

@ -500,6 +500,17 @@ func (s *Server) Run() error {
return <-errChan
}
// HTTPListenAddr exposes `net.Addr` that `Server` is listening to for HTTP connections.
func (s *Server) HTTPListenAddr() net.Addr {
return s.httpListener.Addr()
}
// GRPCListenAddr exposes `net.Addr` that `Server` is listening to for GRPC connections.
func (s *Server) GRPCListenAddr() net.Addr {
return s.grpcListener.Addr()
}
// Stop unblocks Run().
func (s *Server) Stop() {
s.handler.Stop()

@ -1047,7 +1047,7 @@ github.com/uber/jaeger-lib/metrics/prometheus
# github.com/ugorji/go/codec v1.1.7
## explicit
github.com/ugorji/go/codec
# github.com/weaveworks/common v0.0.0-20220706100410-67d27ed40fae
# github.com/weaveworks/common v0.0.0-20220809154356-72ba250fe659
## explicit; go 1.14
github.com/weaveworks/common/aws
github.com/weaveworks/common/errors

Loading…
Cancel
Save