github.com/thanos-io/thanos@v0.32.5/pkg/promclient/promclient_e2e_test.go (about) 1 // Copyright (c) The Thanos Authors. 2 // Licensed under the Apache License 2.0. 3 4 package promclient 5 6 import ( 7 "context" 8 "fmt" 9 "net/url" 10 "os" 11 "path" 12 "testing" 13 "time" 14 15 "github.com/oklog/ulid" 16 "github.com/prometheus/common/model" 17 "github.com/prometheus/prometheus/config" 18 "github.com/prometheus/prometheus/model/labels" 19 "github.com/prometheus/prometheus/model/timestamp" 20 "gopkg.in/yaml.v3" 21 22 "github.com/efficientgo/core/testutil" 23 "github.com/thanos-io/thanos/pkg/block/metadata" 24 "github.com/thanos-io/thanos/pkg/runutil" 25 "github.com/thanos-io/thanos/pkg/testutil/e2eutil" 26 ) 27 28 func TestIsWALFileAccessible_e2e(t *testing.T) { 29 e2eutil.ForeachPrometheus(t, func(t testing.TB, p *e2eutil.Prometheus) { 30 testutil.Ok(t, p.Start()) 31 32 ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) 33 defer cancel() 34 testutil.Ok(t, runutil.Retry(time.Second, ctx.Done(), func() error { return IsWALDirAccessible(p.Dir()) })) 35 36 testutil.NotOk(t, IsWALDirAccessible(path.Join(p.Dir(), "/non-existing"))) 37 testutil.NotOk(t, IsWALDirAccessible(path.Join(p.Dir(), "/../"))) 38 }) 39 } 40 41 func TestExternalLabels_e2e(t *testing.T) { 42 e2eutil.ForeachPrometheus(t, func(t testing.TB, p *e2eutil.Prometheus) { 43 // Keep consistent with the config processing in function (*Client).ExternalLabels. 44 cfg := config.Config{GlobalConfig: config.GlobalConfig{ExternalLabels: []labels.Label{ 45 {Name: "region", Value: "eu-west"}, 46 {Name: "az", Value: "1"}, 47 }}} 48 cfgData, err := yaml.Marshal(cfg) 49 testutil.Ok(t, err) 50 p.SetConfig(string(cfgData)) 51 52 testutil.Ok(t, p.Start()) 53 54 u, err := url.Parse(fmt.Sprintf("http://%s", p.Addr())) 55 testutil.Ok(t, err) 56 57 ext, err := NewDefaultClient().ExternalLabels(context.Background(), u) 58 testutil.Ok(t, err) 59 60 testutil.Equals(t, 2, len(ext)) 61 testutil.Equals(t, "eu-west", ext.Get("region")) 62 testutil.Equals(t, "1", ext.Get("az")) 63 }) 64 } 65 66 func TestConfiguredFlags_e2e(t *testing.T) { 67 e2eutil.ForeachPrometheus(t, func(t testing.TB, p *e2eutil.Prometheus) { 68 testutil.Ok(t, p.Start()) 69 70 u, err := url.Parse(fmt.Sprintf("http://%s", p.Addr())) 71 testutil.Ok(t, err) 72 73 flags, err := NewDefaultClient().ConfiguredFlags(context.Background(), u) 74 testutil.Ok(t, err) 75 76 testutil.Assert(t, flags.WebEnableAdminAPI, "") 77 testutil.Assert(t, !flags.WebEnableLifecycle, "") 78 testutil.Equals(t, p.Dir(), flags.TSDBPath) 79 testutil.Equals(t, int64(2*time.Hour), int64(flags.TSDBMinTime)) 80 testutil.Equals(t, int64(4.8*float64(time.Hour)), int64(flags.TSDBMaxTime)) 81 testutil.Equals(t, int64(2*24*time.Hour), int64(flags.TSDBRetention)) 82 }) 83 } 84 85 func TestSnapshot_e2e(t *testing.T) { 86 e2eutil.ForeachPrometheus(t, func(t testing.TB, p *e2eutil.Prometheus) { 87 now := time.Now() 88 89 ctx := context.Background() 90 // Create artificial block. 91 id, err := e2eutil.CreateBlockWithTombstone( 92 ctx, 93 p.Dir(), 94 []labels.Labels{labels.FromStrings("a", "b")}, 95 10, 96 timestamp.FromTime(now.Add(-6*time.Hour)), 97 timestamp.FromTime(now.Add(-4*time.Hour)), 98 nil, 99 0, 100 metadata.NoneFunc, 101 ) 102 testutil.Ok(t, err) 103 104 testutil.Ok(t, p.Start()) 105 106 u, err := url.Parse(fmt.Sprintf("http://%s", p.Addr())) 107 testutil.Ok(t, err) 108 109 // Prometheus since 2.7.0 don't write empty blocks even if it's head block. So it's no matter passing skip_head true or false here 110 // Pass skipHead = true to support all prometheus versions and assert that snapshot creates only one file 111 // https://github.com/prometheus/tsdb/pull/374. 112 dir, err := NewDefaultClient().Snapshot(ctx, u, true) 113 testutil.Ok(t, err) 114 115 _, err = os.Stat(path.Join(p.Dir(), dir, id.String())) 116 testutil.Ok(t, err) 117 118 files, err := os.ReadDir(path.Join(p.Dir(), dir)) 119 testutil.Ok(t, err) 120 121 for _, f := range files { 122 _, err := ulid.Parse(f.Name()) 123 testutil.Ok(t, err) 124 } 125 126 testutil.Equals(t, 1, len(files)) 127 }) 128 } 129 130 func TestRule_UnmarshalScalarResponse(t *testing.T) { 131 var ( 132 scalarJSONResult = []byte(`[1541196373.677,"1"]`) 133 invalidLengthScalarJSONResult = []byte(`[1541196373.677,"1", "nonsense"]`) 134 invalidDataScalarJSONResult = []byte(`["foo","bar"]`) 135 136 vectorResult model.Vector 137 expectedVector = model.Vector{&model.Sample{ 138 Metric: model.Metric{}, 139 Value: 1, 140 Timestamp: model.Time(1541196373677)}} 141 ) 142 // Test valid input. 143 vectorResult, err := convertScalarJSONToVector(scalarJSONResult) 144 testutil.Ok(t, err) 145 testutil.Equals(t, vectorResult.String(), expectedVector.String()) 146 147 // Test invalid length of scalar data structure. 148 _, err = convertScalarJSONToVector(invalidLengthScalarJSONResult) 149 testutil.NotOk(t, err) 150 151 // Test invalid format of scalar data. 152 _, err = convertScalarJSONToVector(invalidDataScalarJSONResult) 153 testutil.NotOk(t, err) 154 } 155 156 func TestQueryRange_e2e(t *testing.T) { 157 e2eutil.ForeachPrometheus(t, func(t testing.TB, p *e2eutil.Prometheus) { 158 now := time.Now() 159 160 ctx := context.Background() 161 // Create artificial block. 162 _, err := e2eutil.CreateBlock( 163 ctx, 164 p.Dir(), 165 []labels.Labels{labels.FromStrings("a", "b")}, 166 10, 167 timestamp.FromTime(now.Add(-2*time.Hour)), 168 timestamp.FromTime(now), 169 nil, 170 0, 171 metadata.NoneFunc, 172 ) 173 testutil.Ok(t, err) 174 175 testutil.Ok(t, p.Start()) 176 177 u, err := url.Parse(fmt.Sprintf("http://%s", p.Addr())) 178 testutil.Ok(t, err) 179 180 res, _, _, err := NewDefaultClient().QueryRange( 181 ctx, 182 u, 183 `{a="b"}`, 184 timestamp.FromTime(now.Add(-2*time.Hour)), 185 timestamp.FromTime(now), 186 14, 187 QueryOptions{}, 188 ) 189 testutil.Ok(t, err) 190 191 testutil.Equals(t, len(res) > 0, true) 192 }) 193 }