github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/scrape/discovery/http/http_test.go (about) 1 // Copyright 2021 The Prometheus Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package http 15 16 import ( 17 "context" 18 "fmt" 19 nhttp "net/http" 20 "net/http/httptest" 21 "testing" 22 "time" 23 24 "github.com/pyroscope-io/pyroscope/pkg/scrape/config" 25 "github.com/pyroscope-io/pyroscope/pkg/scrape/discovery/targetgroup" 26 "github.com/pyroscope-io/pyroscope/pkg/scrape/model" 27 "github.com/sirupsen/logrus" 28 "github.com/stretchr/testify/require" 29 ) 30 31 func TestHTTPValidRefresh(t *testing.T) { 32 ts := httptest.NewServer(nhttp.FileServer(nhttp.Dir("./fixtures"))) 33 t.Cleanup(ts.Close) 34 35 cfg := SDConfig{ 36 HTTPClientConfig: config.DefaultHTTPClientConfig, 37 URL: ts.URL + "/http_sd.good.json", 38 RefreshInterval: model.Duration(30 * time.Second), 39 } 40 41 d, err := NewDiscovery(&cfg, logrus.New()) 42 require.NoError(t, err) 43 44 ctx := context.Background() 45 tgs, err := d.refresh(ctx) 46 require.NoError(t, err) 47 48 expectedTargets := []*targetgroup.Group{ 49 { 50 Targets: []model.LabelSet{ 51 { 52 model.AppNameLabel: model.LabelValue("test"), 53 model.AddressLabel: model.LabelValue("127.0.0.1:9090"), 54 model.SpyNameLabel: model.LabelValue(""), 55 }, 56 }, 57 Labels: model.LabelSet{ 58 model.LabelName("__meta_datacenter"): model.LabelValue("bru1"), 59 model.LabelName("__meta_url"): model.LabelValue(ts.URL + "/http_sd.good.json"), 60 }, 61 Source: urlSource(ts.URL+"/http_sd.good.json", 0), 62 }, 63 } 64 require.Equal(t, tgs, expectedTargets) 65 } 66 67 func TestHTTPInvalidCode(t *testing.T) { 68 ts := httptest.NewServer(nhttp.HandlerFunc(func(w nhttp.ResponseWriter, r *nhttp.Request) { 69 w.WriteHeader(nhttp.StatusBadRequest) 70 })) 71 72 t.Cleanup(ts.Close) 73 74 cfg := SDConfig{ 75 HTTPClientConfig: config.DefaultHTTPClientConfig, 76 URL: ts.URL, 77 RefreshInterval: model.Duration(30 * time.Second), 78 } 79 80 d, err := NewDiscovery(&cfg, logrus.New()) 81 require.NoError(t, err) 82 83 ctx := context.Background() 84 _, err = d.refresh(ctx) 85 require.EqualError(t, err, "server returned HTTP status 400 Bad Request") 86 } 87 88 func TestHTTPInvalidFormat(t *testing.T) { 89 ts := httptest.NewServer(nhttp.HandlerFunc(func(w nhttp.ResponseWriter, r *nhttp.Request) { 90 fmt.Fprintln(w, "{}") 91 })) 92 93 t.Cleanup(ts.Close) 94 95 cfg := SDConfig{ 96 HTTPClientConfig: config.DefaultHTTPClientConfig, 97 URL: ts.URL, 98 RefreshInterval: model.Duration(30 * time.Second), 99 } 100 101 d, err := NewDiscovery(&cfg, logrus.New()) 102 require.NoError(t, err) 103 104 ctx := context.Background() 105 _, err = d.refresh(ctx) 106 require.EqualError(t, err, `unsupported content type "text/plain; charset=utf-8"`) 107 } 108 109 func TestContentTypeRegex(t *testing.T) { 110 cases := []struct { 111 header string 112 match bool 113 }{ 114 { 115 header: "application/json;charset=utf-8", 116 match: true, 117 }, 118 { 119 header: "application/json;charset=UTF-8", 120 match: true, 121 }, 122 { 123 header: "Application/JSON;Charset=\"utf-8\"", 124 match: true, 125 }, 126 { 127 header: "application/json; charset=\"utf-8\"", 128 match: true, 129 }, 130 { 131 header: "application/json", 132 match: true, 133 }, 134 { 135 header: "application/jsonl; charset=\"utf-8\"", 136 match: false, 137 }, 138 { 139 header: "application/json;charset=UTF-9", 140 match: false, 141 }, 142 { 143 header: "application /json;charset=UTF-8", 144 match: false, 145 }, 146 { 147 header: "application/ json;charset=UTF-8", 148 match: false, 149 }, 150 { 151 header: "application/json;", 152 match: false, 153 }, 154 { 155 header: "charset=UTF-8", 156 match: false, 157 }, 158 } 159 160 for _, test := range cases { 161 t.Run(test.header, func(t *testing.T) { 162 require.Equal(t, test.match, matchContentType.MatchString(test.header)) 163 }) 164 } 165 } 166 167 func TestSourceDisappeared(t *testing.T) { 168 var stubResponse string 169 ts := httptest.NewServer(nhttp.HandlerFunc(func(w nhttp.ResponseWriter, r *nhttp.Request) { 170 w.Header().Set("Content-Type", "application/json") 171 fmt.Fprintln(w, stubResponse) 172 })) 173 t.Cleanup(ts.Close) 174 175 cases := []struct { 176 responses []string 177 expectedTargets [][]*targetgroup.Group 178 }{ 179 { 180 responses: []string{ 181 `[]`, 182 `[]`, 183 }, 184 expectedTargets: [][]*targetgroup.Group{{}, {}}, 185 }, 186 { 187 responses: []string{ 188 `[{"labels": {"k": "1"}, "targets": ["127.0.0.1"],"application":"test"}]`, 189 `[{"labels": {"k": "1"}, "targets": ["127.0.0.1"],"application":"test"}, 190 {"labels": {"k": "2"}, "targets": ["127.0.0.1"],"application":"test1"}]`, 191 }, 192 expectedTargets: [][]*targetgroup.Group{ 193 { 194 { 195 Targets: []model.LabelSet{ 196 { 197 model.AppNameLabel: model.LabelValue("test"), 198 model.AddressLabel: model.LabelValue("127.0.0.1"), 199 model.SpyNameLabel: model.LabelValue(""), 200 }, 201 }, 202 Labels: model.LabelSet{ 203 model.LabelName("k"): model.LabelValue("1"), 204 model.LabelName("__meta_url"): model.LabelValue(ts.URL), 205 }, 206 Source: urlSource(ts.URL, 0), 207 }, 208 }, 209 { 210 { 211 Targets: []model.LabelSet{ 212 { 213 model.AppNameLabel: model.LabelValue("test"), 214 model.AddressLabel: model.LabelValue("127.0.0.1"), 215 model.SpyNameLabel: model.LabelValue(""), 216 }, 217 }, 218 Labels: model.LabelSet{ 219 model.LabelName("k"): model.LabelValue("1"), 220 model.LabelName("__meta_url"): model.LabelValue(ts.URL), 221 }, 222 Source: urlSource(ts.URL, 0), 223 }, 224 { 225 Targets: []model.LabelSet{ 226 { 227 model.AppNameLabel: model.LabelValue("test1"), 228 model.AddressLabel: model.LabelValue("127.0.0.1"), 229 model.SpyNameLabel: model.LabelValue("")}, 230 }, 231 Labels: model.LabelSet{ 232 model.LabelName("k"): model.LabelValue("2"), 233 model.LabelName("__meta_url"): model.LabelValue(ts.URL), 234 }, 235 Source: urlSource(ts.URL, 1), 236 }, 237 }, 238 }, 239 }, 240 { 241 responses: []string{ 242 `[{"labels": {"k": "1"}, "targets": ["127.0.0.1"],"application":"test1"}, 243 {"labels": {"k": "2"}, "targets": ["127.0.0.1"],"application":"test2"}]`, 244 `[{"labels": {"k": "1"}, "targets": ["127.0.0.1"],"application":"test1"}]`, 245 }, 246 expectedTargets: [][]*targetgroup.Group{ 247 { 248 { 249 Targets: []model.LabelSet{ 250 { 251 model.AppNameLabel: model.LabelValue("test1"), 252 model.AddressLabel: model.LabelValue("127.0.0.1"), 253 model.SpyNameLabel: model.LabelValue(""), 254 }, 255 }, 256 Labels: model.LabelSet{ 257 model.LabelName("k"): model.LabelValue("1"), 258 model.LabelName("__meta_url"): model.LabelValue(ts.URL), 259 }, 260 Source: urlSource(ts.URL, 0), 261 }, 262 { 263 Targets: []model.LabelSet{ 264 { 265 model.AppNameLabel: model.LabelValue("test2"), 266 model.AddressLabel: model.LabelValue("127.0.0.1"), 267 model.SpyNameLabel: model.LabelValue(""), 268 }, 269 }, 270 Labels: model.LabelSet{ 271 model.LabelName("k"): model.LabelValue("2"), 272 model.LabelName("__meta_url"): model.LabelValue(ts.URL), 273 }, 274 Source: urlSource(ts.URL, 1), 275 }, 276 }, 277 { 278 { 279 Targets: []model.LabelSet{ 280 { 281 model.AppNameLabel: model.LabelValue("test1"), 282 model.AddressLabel: model.LabelValue("127.0.0.1"), 283 model.SpyNameLabel: model.LabelValue(""), 284 }, 285 }, 286 Labels: model.LabelSet{ 287 model.LabelName("k"): model.LabelValue("1"), 288 model.LabelName("__meta_url"): model.LabelValue(ts.URL), 289 }, 290 Source: urlSource(ts.URL, 0), 291 }, 292 { 293 Targets: nil, 294 Labels: nil, 295 Source: urlSource(ts.URL, 1), 296 }, 297 }, 298 }, 299 }, 300 { 301 responses: []string{ 302 `[{"labels": {"k": "1"}, "targets": ["127.0.0.1"], "application":"test1"}, 303 {"labels": {"k": "2"}, "targets": ["127.0.0.1"],"application":"test2"}, 304 {"labels": {"k": "3"}, "targets": ["127.0.0.1"],"application":"test3"}]`, 305 `[{"labels": {"k": "1"}, "targets": ["127.0.0.1"],"application":"test1"}]`, 306 `[{"labels": {"k": "v"}, "targets": ["127.0.0.2"],"application":"testv"}, {"labels": {"k": "vv"}, "targets": ["127.0.0.3"],"application":"testvv"}]`, 307 }, 308 expectedTargets: [][]*targetgroup.Group{ 309 { 310 { 311 Targets: []model.LabelSet{ 312 { 313 model.AddressLabel: model.LabelValue("127.0.0.1"), 314 model.AppNameLabel: "test1", 315 model.SpyNameLabel: model.LabelValue(""), 316 }, 317 }, 318 Labels: model.LabelSet{ 319 model.LabelName("k"): model.LabelValue("1"), 320 model.LabelName("__meta_url"): model.LabelValue(ts.URL), 321 }, 322 Source: urlSource(ts.URL, 0), 323 }, 324 { 325 Targets: []model.LabelSet{ 326 { 327 model.AddressLabel: model.LabelValue("127.0.0.1"), 328 model.AppNameLabel: "test2", 329 model.SpyNameLabel: model.LabelValue(""), 330 }, 331 }, 332 Labels: model.LabelSet{ 333 model.LabelName("k"): model.LabelValue("2"), 334 model.LabelName("__meta_url"): model.LabelValue(ts.URL), 335 }, 336 Source: urlSource(ts.URL, 1), 337 }, 338 { 339 Targets: []model.LabelSet{ 340 { 341 model.AddressLabel: model.LabelValue("127.0.0.1"), 342 model.AppNameLabel: "test3", 343 model.SpyNameLabel: model.LabelValue(""), 344 }, 345 }, 346 Labels: model.LabelSet{ 347 model.LabelName("k"): model.LabelValue("3"), 348 model.LabelName("__meta_url"): model.LabelValue(ts.URL), 349 }, 350 Source: urlSource(ts.URL, 2), 351 }, 352 }, 353 { 354 { 355 Targets: []model.LabelSet{ 356 { 357 model.AppNameLabel: "test1", 358 model.AddressLabel: model.LabelValue("127.0.0.1"), 359 model.SpyNameLabel: model.LabelValue(""), 360 }, 361 }, 362 Labels: model.LabelSet{ 363 model.LabelName("k"): model.LabelValue("1"), 364 model.LabelName("__meta_url"): model.LabelValue(ts.URL), 365 }, 366 Source: urlSource(ts.URL, 0), 367 }, 368 { 369 Targets: nil, 370 Labels: nil, 371 Source: urlSource(ts.URL, 1), 372 }, 373 { 374 Targets: nil, 375 Labels: nil, 376 Source: urlSource(ts.URL, 2), 377 }, 378 }, 379 { 380 { 381 Targets: []model.LabelSet{ 382 { 383 model.AddressLabel: model.LabelValue("127.0.0.2"), 384 model.AppNameLabel: "testv", 385 model.SpyNameLabel: model.LabelValue(""), 386 }, 387 }, 388 Labels: model.LabelSet{ 389 model.LabelName("k"): model.LabelValue("v"), 390 model.LabelName("__meta_url"): model.LabelValue(ts.URL), 391 }, 392 Source: urlSource(ts.URL, 0), 393 }, 394 { 395 Targets: []model.LabelSet{ 396 { 397 model.AddressLabel: model.LabelValue("127.0.0.3"), 398 model.AppNameLabel: "testvv", 399 model.SpyNameLabel: model.LabelValue(""), 400 }, 401 }, 402 Labels: model.LabelSet{ 403 model.LabelName("k"): model.LabelValue("vv"), 404 model.LabelName("__meta_url"): model.LabelValue(ts.URL), 405 }, 406 Source: urlSource(ts.URL, 1), 407 }, 408 }, 409 }, 410 }, 411 } 412 413 cfg := SDConfig{ 414 HTTPClientConfig: config.DefaultHTTPClientConfig, 415 URL: ts.URL, 416 RefreshInterval: model.Duration(1 * time.Second), 417 } 418 d, err := NewDiscovery(&cfg, logrus.New()) 419 require.NoError(t, err) 420 for _, test := range cases { 421 ctx := context.Background() 422 for i, res := range test.responses { 423 stubResponse = res 424 tgs, err := d.refresh(ctx) 425 require.NoError(t, err) 426 require.Equal(t, test.expectedTargets[i], tgs) 427 } 428 } 429 }