github.com/thanos-io/thanos@v0.32.5/test/e2e/targets_api_test.go (about)

     1  // Copyright (c) The Thanos Authors.
     2  // Licensed under the Apache License 2.0.
     3  
     4  package e2e_test
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"os"
    10  	"reflect"
    11  	"sort"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/efficientgo/e2e"
    16  	e2emon "github.com/efficientgo/e2e/monitoring"
    17  	"github.com/go-kit/log"
    18  	"github.com/pkg/errors"
    19  
    20  	"github.com/efficientgo/core/testutil"
    21  	"github.com/thanos-io/thanos/pkg/promclient"
    22  	"github.com/thanos-io/thanos/pkg/runutil"
    23  	"github.com/thanos-io/thanos/pkg/store/labelpb"
    24  	"github.com/thanos-io/thanos/pkg/targets/targetspb"
    25  	"github.com/thanos-io/thanos/test/e2e/e2ethanos"
    26  )
    27  
    28  func TestTargetsAPI_Fanout(t *testing.T) {
    29  	t.Parallel()
    30  
    31  	e, err := e2e.NewDockerEnvironment("targets-fanout")
    32  	testutil.Ok(t, err)
    33  	t.Cleanup(e2ethanos.CleanScenario(t, e))
    34  
    35  	// 2x Prometheus.
    36  	prom1, sidecar1 := e2ethanos.NewPrometheusWithSidecar(
    37  		e,
    38  		"prom1",
    39  		e2ethanos.DefaultPromConfig("ha", 0, "", "", e2ethanos.LocalPrometheusTarget, "localhost:80"),
    40  		"",
    41  		e2ethanos.DefaultPrometheusImage(), "",
    42  	)
    43  	prom2, sidecar2 := e2ethanos.NewPrometheusWithSidecar(
    44  		e,
    45  		"prom2",
    46  		e2ethanos.DefaultPromConfig("ha", 1, "", "", e2ethanos.LocalPrometheusTarget, "localhost:80"),
    47  		"",
    48  		e2ethanos.DefaultPrometheusImage(), "",
    49  	)
    50  	testutil.Ok(t, e2e.StartAndWaitReady(prom1, sidecar1, prom2, sidecar2))
    51  
    52  	stores := []string{sidecar1.InternalEndpoint("grpc"), sidecar2.InternalEndpoint("grpc")}
    53  	q := e2ethanos.NewQuerierBuilder(e, "query", stores...).
    54  		WithTargetAddresses(stores...).
    55  		Init()
    56  	testutil.Ok(t, err)
    57  	testutil.Ok(t, e2e.StartAndWaitReady(q))
    58  
    59  	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
    60  	t.Cleanup(cancel)
    61  
    62  	testutil.Ok(t, q.WaitSumMetricsWithOptions(e2emon.Equals(2), []string{"thanos_store_nodes_grpc_connections"}, e2emon.WaitMissingMetrics()))
    63  
    64  	targetAndAssert(t, ctx, q.Endpoint("http"), "", &targetspb.TargetDiscovery{
    65  		ActiveTargets: []*targetspb.ActiveTarget{
    66  			{
    67  				DiscoveredLabels: labelpb.ZLabelSet{Labels: []labelpb.ZLabel{
    68  					{Name: "__address__", Value: "localhost:9090"},
    69  					{Name: "__metrics_path__", Value: "/metrics"},
    70  					{Name: "__scheme__", Value: "http"},
    71  					{Name: "__scrape_interval__", Value: "1s"},
    72  					{Name: "__scrape_timeout__", Value: "1s"},
    73  					{Name: "job", Value: "myself"},
    74  					{Name: "prometheus", Value: "ha"},
    75  				}},
    76  				Labels: labelpb.ZLabelSet{Labels: []labelpb.ZLabel{
    77  					{Name: "instance", Value: "localhost:9090"},
    78  					{Name: "job", Value: "myself"},
    79  					{Name: "prometheus", Value: "ha"},
    80  				}},
    81  				ScrapePool: "myself",
    82  				ScrapeUrl:  "http://localhost:9090/metrics",
    83  				Health:     targetspb.TargetHealth_UP,
    84  			},
    85  		},
    86  		DroppedTargets: []*targetspb.DroppedTarget{
    87  			{
    88  				DiscoveredLabels: labelpb.ZLabelSet{Labels: []labelpb.ZLabel{
    89  					{Name: "__address__", Value: "localhost:80"},
    90  					{Name: "__metrics_path__", Value: "/metrics"},
    91  					{Name: "__scheme__", Value: "http"},
    92  					{Name: "__scrape_interval__", Value: "1s"},
    93  					{Name: "__scrape_timeout__", Value: "1s"},
    94  					{Name: "job", Value: "myself"},
    95  					{Name: "prometheus", Value: "ha"},
    96  				}},
    97  			},
    98  		},
    99  	})
   100  }
   101  
   102  func targetAndAssert(t *testing.T, ctx context.Context, addr, state string, want *targetspb.TargetDiscovery) {
   103  	t.Helper()
   104  
   105  	fmt.Println("targetAndAssert: Waiting for results for targets state", state)
   106  
   107  	logger := log.NewLogfmtLogger(os.Stdout)
   108  	testutil.Ok(t, runutil.RetryWithLog(logger, time.Second, ctx.Done(), func() error {
   109  		res, err := promclient.NewDefaultClient().TargetsInGRPC(ctx, urlParse(t, "http://"+addr), state)
   110  		if err != nil {
   111  			return err
   112  		}
   113  
   114  		if len(res.ActiveTargets) != len(want.ActiveTargets) {
   115  			return errors.Errorf("unexpected result.ActiveTargets size, want %d; got: %d result: %v", len(want.ActiveTargets), len(res.ActiveTargets), res)
   116  		}
   117  
   118  		if len(res.DroppedTargets) != len(want.DroppedTargets) {
   119  			return errors.Errorf("unexpected result.DroppedTargets size, want %d; got: %d result: %v", len(want.DroppedTargets), len(res.DroppedTargets), res)
   120  		}
   121  
   122  		for it := range res.ActiveTargets {
   123  			res.ActiveTargets[it].LastScrape = time.Time{}
   124  			res.ActiveTargets[it].LastScrapeDuration = 0
   125  			res.ActiveTargets[it].GlobalUrl = ""
   126  		}
   127  
   128  		sort.Slice(res.ActiveTargets, func(i, j int) bool { return res.ActiveTargets[i].Compare(res.ActiveTargets[j]) < 0 })
   129  		sort.Slice(res.DroppedTargets, func(i, j int) bool { return res.DroppedTargets[i].Compare(res.DroppedTargets[j]) < 0 })
   130  
   131  		if !reflect.DeepEqual(want, res) {
   132  			return errors.Errorf("unexpected result\nwant %v\ngot: %v", want, res)
   133  		}
   134  
   135  		return nil
   136  	}))
   137  }