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  }