github.com/thanos-io/thanos@v0.32.5/test/e2e/info_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 "encoding/json" 9 "fmt" 10 "io" 11 "net/http" 12 "path" 13 "testing" 14 "time" 15 16 "github.com/efficientgo/e2e" 17 "github.com/prometheus/prometheus/model/labels" 18 19 "github.com/thanos-io/objstore/client" 20 21 "github.com/efficientgo/core/testutil" 22 e2edb "github.com/efficientgo/e2e/db" 23 "github.com/thanos-io/thanos/pkg/query" 24 "github.com/thanos-io/thanos/pkg/runutil" 25 "github.com/thanos-io/thanos/test/e2e/e2ethanos" 26 ) 27 28 func TestInfo(t *testing.T) { 29 t.Parallel() 30 31 e, err := e2e.NewDockerEnvironment("e2e-test-info") 32 testutil.Ok(t, err) 33 t.Cleanup(e2ethanos.CleanScenario(t, e)) 34 35 prom1, sidecar1 := e2ethanos.NewPrometheusWithSidecar(e, "alone1", e2ethanos.DefaultPromConfig("prom-alone1", 0, "", "", e2ethanos.LocalPrometheusTarget), "", e2ethanos.DefaultPrometheusImage(), "") 36 prom2, sidecar2 := e2ethanos.NewPrometheusWithSidecar(e, "alone2", e2ethanos.DefaultPromConfig("prom-alone2", 0, "", "", e2ethanos.LocalPrometheusTarget), "", e2ethanos.DefaultPrometheusImage(), "") 37 prom3, sidecar3 := e2ethanos.NewPrometheusWithSidecar(e, "alone3", e2ethanos.DefaultPromConfig("prom-alone3", 0, "", "", e2ethanos.LocalPrometheusTarget), "", e2ethanos.DefaultPrometheusImage(), "") 38 testutil.Ok(t, e2e.StartAndWaitReady(prom1, sidecar1, prom2, sidecar2, prom3, sidecar3)) 39 40 const bucket = "info-api-test" 41 m := e2edb.NewMinio(e, "thanos-minio", bucket, e2edb.WithMinioTLS()) 42 testutil.Ok(t, e2e.StartAndWaitReady(m)) 43 store := e2ethanos.NewStoreGW( 44 e, 45 "1", 46 client.BucketConfig{ 47 Type: client.S3, 48 Config: e2ethanos.NewS3Config(bucket, m.InternalEndpoint("http"), m.InternalDir()), 49 }, 50 "", 51 "", 52 nil, 53 ) 54 testutil.Ok(t, e2e.StartAndWaitReady(store)) 55 56 // Register `sidecar1` in all flags (i.e. '--store', '--rule', '--target', '--metadata', '--exemplar', '--endpoint') to verify 57 // '--endpoint' flag works properly works together with other flags ('--target', '--metadata' etc.). 58 // Register 2 sidecars and 1 storeGW using '--endpoint'. 59 // Register `sidecar3` twice to verify it is deduplicated. 60 q := e2ethanos.NewQuerierBuilder(e, "1", sidecar1.InternalEndpoint("grpc")). 61 WithTargetAddresses(sidecar1.InternalEndpoint("grpc")). 62 WithMetadataAddresses(sidecar1.InternalEndpoint("grpc")). 63 WithExemplarAddresses(sidecar1.InternalEndpoint("grpc")). 64 WithRuleAddresses(sidecar1.InternalEndpoint("grpc")). 65 WithEndpoints( 66 sidecar1.InternalEndpoint("grpc"), 67 sidecar2.InternalEndpoint("grpc"), 68 sidecar3.InternalEndpoint("grpc"), 69 store.InternalEndpoint("grpc"), 70 ). 71 Init() 72 testutil.Ok(t, e2e.StartAndWaitReady(q)) 73 74 expected := map[string][]query.EndpointStatus{ 75 "sidecar": { 76 { 77 Name: "e2e-test-info-sidecar-alone1:9091", 78 LabelSets: []labels.Labels{{ 79 { 80 Name: "prometheus", 81 Value: "prom-alone1", 82 }, 83 { 84 Name: "replica", 85 Value: "0", 86 }, 87 }}, 88 }, 89 { 90 Name: "e2e-test-info-sidecar-alone2:9091", 91 LabelSets: []labels.Labels{{ 92 { 93 Name: "prometheus", 94 Value: "prom-alone2", 95 }, 96 { 97 Name: "replica", 98 Value: "0", 99 }, 100 }}, 101 }, 102 { 103 Name: "e2e-test-info-sidecar-alone3:9091", 104 LabelSets: []labels.Labels{{ 105 { 106 Name: "prometheus", 107 Value: "prom-alone3", 108 }, 109 { 110 Name: "replica", 111 Value: "0", 112 }, 113 }}, 114 }, 115 }, 116 "store": { 117 { 118 Name: "e2e-test-info-store-gw-1:9091", 119 LabelSets: []labels.Labels{}, 120 }, 121 }, 122 } 123 124 url := "http://" + path.Join(q.Endpoint("http"), "/api/v1/stores") 125 126 ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) 127 defer cancel() 128 129 err = runutil.Retry(time.Second, ctx.Done(), func() error { 130 131 req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) 132 if err != nil { 133 return err 134 } 135 136 resp, err := http.DefaultClient.Do(req) 137 if err != nil { 138 return err 139 } 140 141 body, err := io.ReadAll(resp.Body) 142 defer runutil.CloseWithErrCapture(&err, resp.Body, "response body close") 143 144 var res struct { 145 Data map[string][]query.EndpointStatus `json:"data"` 146 } 147 148 err = json.Unmarshal(body, &res) 149 if err != nil { 150 return err 151 } 152 153 if err = assertStoreStatus(t, "sidecar", res.Data, expected); err != nil { 154 return err 155 } 156 157 if err = assertStoreStatus(t, "store", res.Data, expected); err != nil { 158 return err 159 } 160 161 return nil 162 }) 163 testutil.Ok(t, err) 164 } 165 166 func assertStoreStatus(t *testing.T, component string, res map[string][]query.EndpointStatus, expected map[string][]query.EndpointStatus) error { 167 t.Helper() 168 169 if len(res[component]) != len(expected[component]) { 170 return fmt.Errorf("expected %d %s, got: %d", len(expected[component]), component, len(res[component])) 171 } 172 173 for i, v := range res[component] { 174 // Set value of the fields which keep changing in every test run to their default value. 175 v.MaxTime = 0 176 v.MinTime = 0 177 v.LastCheck = time.Time{} 178 179 testutil.Equals(t, expected[component][i], v) 180 } 181 182 return nil 183 }