prometheus
456 строк · 11.7 Кб
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
14package http15
16import (17"context"18"fmt"19"net/http"20"net/http/httptest"21"testing"22"time"23
24"github.com/go-kit/log"25"github.com/prometheus/client_golang/prometheus"26dto "github.com/prometheus/client_model/go"27"github.com/prometheus/common/config"28"github.com/prometheus/common/model"29"github.com/stretchr/testify/require"30
31"github.com/prometheus/prometheus/discovery"32"github.com/prometheus/prometheus/discovery/targetgroup"33)
34
35func TestHTTPValidRefresh(t *testing.T) {36ts := httptest.NewServer(http.FileServer(http.Dir("./fixtures")))37t.Cleanup(ts.Close)38
39cfg := SDConfig{40HTTPClientConfig: config.DefaultHTTPClientConfig,41URL: ts.URL + "/http_sd.good.json",42RefreshInterval: model.Duration(30 * time.Second),43}44
45reg := prometheus.NewRegistry()46refreshMetrics := discovery.NewRefreshMetrics(reg)47defer refreshMetrics.Unregister()48metrics := cfg.NewDiscovererMetrics(reg, refreshMetrics)49require.NoError(t, metrics.Register())50defer metrics.Unregister()51
52d, err := NewDiscovery(&cfg, log.NewNopLogger(), nil, metrics)53require.NoError(t, err)54
55ctx := context.Background()56tgs, err := d.Refresh(ctx)57require.NoError(t, err)58
59expectedTargets := []*targetgroup.Group{60{61Targets: []model.LabelSet{62{63model.AddressLabel: model.LabelValue("127.0.0.1:9090"),64},65},66Labels: model.LabelSet{67model.LabelName("__meta_datacenter"): model.LabelValue("bru1"),68model.LabelName("__meta_url"): model.LabelValue(ts.URL + "/http_sd.good.json"),69},70Source: urlSource(ts.URL+"/http_sd.good.json", 0),71},72}73require.Equal(t, expectedTargets, tgs)74require.Equal(t, 0.0, getFailureCount(d.metrics.failuresCount))75}
76
77func TestHTTPInvalidCode(t *testing.T) {78ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {79w.WriteHeader(http.StatusBadRequest)80}))81
82t.Cleanup(ts.Close)83
84cfg := SDConfig{85HTTPClientConfig: config.DefaultHTTPClientConfig,86URL: ts.URL,87RefreshInterval: model.Duration(30 * time.Second),88}89
90reg := prometheus.NewRegistry()91refreshMetrics := discovery.NewRefreshMetrics(reg)92defer refreshMetrics.Unregister()93metrics := cfg.NewDiscovererMetrics(reg, refreshMetrics)94require.NoError(t, metrics.Register())95defer metrics.Unregister()96
97d, err := NewDiscovery(&cfg, log.NewNopLogger(), nil, metrics)98require.NoError(t, err)99
100ctx := context.Background()101_, err = d.Refresh(ctx)102require.EqualError(t, err, "server returned HTTP status 400 Bad Request")103require.Equal(t, 1.0, getFailureCount(d.metrics.failuresCount))104}
105
106func TestHTTPInvalidFormat(t *testing.T) {107ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {108fmt.Fprintln(w, "{}")109}))110
111t.Cleanup(ts.Close)112
113cfg := SDConfig{114HTTPClientConfig: config.DefaultHTTPClientConfig,115URL: ts.URL,116RefreshInterval: model.Duration(30 * time.Second),117}118
119reg := prometheus.NewRegistry()120refreshMetrics := discovery.NewRefreshMetrics(reg)121defer refreshMetrics.Unregister()122metrics := cfg.NewDiscovererMetrics(reg, refreshMetrics)123require.NoError(t, metrics.Register())124defer metrics.Unregister()125
126d, err := NewDiscovery(&cfg, log.NewNopLogger(), nil, metrics)127require.NoError(t, err)128
129ctx := context.Background()130_, err = d.Refresh(ctx)131require.EqualError(t, err, `unsupported content type "text/plain; charset=utf-8"`)132require.Equal(t, 1.0, getFailureCount(d.metrics.failuresCount))133}
134
135func getFailureCount(failuresCount prometheus.Counter) float64 {136failureChan := make(chan prometheus.Metric)137
138go func() {139failuresCount.Collect(failureChan)140close(failureChan)141}()142
143var counter dto.Metric144for {145metric, ok := <-failureChan146if ok == false {147break148}149metric.Write(&counter)150}151
152return *counter.Counter.Value153}
154
155func TestContentTypeRegex(t *testing.T) {156cases := []struct {157header string158match bool159}{160{161header: "application/json;charset=utf-8",162match: true,163},164{165header: "application/json;charset=UTF-8",166match: true,167},168{169header: "Application/JSON;Charset=\"utf-8\"",170match: true,171},172{173header: "application/json; charset=\"utf-8\"",174match: true,175},176{177header: "application/json",178match: true,179},180{181header: "application/jsonl; charset=\"utf-8\"",182match: false,183},184{185header: "application/json;charset=UTF-9",186match: false,187},188{189header: "application /json;charset=UTF-8",190match: false,191},192{193header: "application/ json;charset=UTF-8",194match: false,195},196{197header: "application/json;",198match: false,199},200{201header: "charset=UTF-8",202match: false,203},204}205
206for _, test := range cases {207t.Run(test.header, func(t *testing.T) {208require.Equal(t, test.match, matchContentType.MatchString(test.header))209})210}211}
212
213func TestSourceDisappeared(t *testing.T) {214var stubResponse string215ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {216w.Header().Set("Content-Type", "application/json")217fmt.Fprintln(w, stubResponse)218}))219t.Cleanup(ts.Close)220
221cases := []struct {222responses []string223expectedTargets [][]*targetgroup.Group224}{225{226responses: []string{227`[]`,228`[]`,229},230expectedTargets: [][]*targetgroup.Group{{}, {}},231},232{233responses: []string{234`[{"labels": {"k": "1"}, "targets": ["127.0.0.1"]}]`,235`[{"labels": {"k": "1"}, "targets": ["127.0.0.1"]}, {"labels": {"k": "2"}, "targets": ["127.0.0.1"]}]`,236},237expectedTargets: [][]*targetgroup.Group{238{239{240Targets: []model.LabelSet{241{242model.AddressLabel: model.LabelValue("127.0.0.1"),243},244},245Labels: model.LabelSet{246model.LabelName("k"): model.LabelValue("1"),247model.LabelName("__meta_url"): model.LabelValue(ts.URL),248},249Source: urlSource(ts.URL, 0),250},251},252{253{254Targets: []model.LabelSet{255{256model.AddressLabel: model.LabelValue("127.0.0.1"),257},258},259Labels: model.LabelSet{260model.LabelName("k"): model.LabelValue("1"),261model.LabelName("__meta_url"): model.LabelValue(ts.URL),262},263Source: urlSource(ts.URL, 0),264},265{266Targets: []model.LabelSet{267{268model.AddressLabel: model.LabelValue("127.0.0.1"),269},270},271Labels: model.LabelSet{272model.LabelName("k"): model.LabelValue("2"),273model.LabelName("__meta_url"): model.LabelValue(ts.URL),274},275Source: urlSource(ts.URL, 1),276},277},278},279},280{281responses: []string{282`[{"labels": {"k": "1"}, "targets": ["127.0.0.1"]}, {"labels": {"k": "2"}, "targets": ["127.0.0.1"]}]`,283`[{"labels": {"k": "1"}, "targets": ["127.0.0.1"]}]`,284},285expectedTargets: [][]*targetgroup.Group{286{287{288Targets: []model.LabelSet{289{290model.AddressLabel: model.LabelValue("127.0.0.1"),291},292},293Labels: model.LabelSet{294model.LabelName("k"): model.LabelValue("1"),295model.LabelName("__meta_url"): model.LabelValue(ts.URL),296},297Source: urlSource(ts.URL, 0),298},299{300Targets: []model.LabelSet{301{302model.AddressLabel: model.LabelValue("127.0.0.1"),303},304},305Labels: model.LabelSet{306model.LabelName("k"): model.LabelValue("2"),307model.LabelName("__meta_url"): model.LabelValue(ts.URL),308},309Source: urlSource(ts.URL, 1),310},311},312{313{314Targets: []model.LabelSet{315{316model.AddressLabel: model.LabelValue("127.0.0.1"),317},318},319Labels: model.LabelSet{320model.LabelName("k"): model.LabelValue("1"),321model.LabelName("__meta_url"): model.LabelValue(ts.URL),322},323Source: urlSource(ts.URL, 0),324},325{326Targets: nil,327Labels: nil,328Source: urlSource(ts.URL, 1),329},330},331},332},333{334responses: []string{335`[{"labels": {"k": "1"}, "targets": ["127.0.0.1"]}, {"labels": {"k": "2"}, "targets": ["127.0.0.1"]}, {"labels": {"k": "3"}, "targets": ["127.0.0.1"]}]`,336`[{"labels": {"k": "1"}, "targets": ["127.0.0.1"]}]`,337`[{"labels": {"k": "v"}, "targets": ["127.0.0.2"]}, {"labels": {"k": "vv"}, "targets": ["127.0.0.3"]}]`,338},339expectedTargets: [][]*targetgroup.Group{340{341{342Targets: []model.LabelSet{343{344model.AddressLabel: model.LabelValue("127.0.0.1"),345},346},347Labels: model.LabelSet{348model.LabelName("k"): model.LabelValue("1"),349model.LabelName("__meta_url"): model.LabelValue(ts.URL),350},351Source: urlSource(ts.URL, 0),352},353{354Targets: []model.LabelSet{355{356model.AddressLabel: model.LabelValue("127.0.0.1"),357},358},359Labels: model.LabelSet{360model.LabelName("k"): model.LabelValue("2"),361model.LabelName("__meta_url"): model.LabelValue(ts.URL),362},363Source: urlSource(ts.URL, 1),364},365{366Targets: []model.LabelSet{367{368model.AddressLabel: model.LabelValue("127.0.0.1"),369},370},371Labels: model.LabelSet{372model.LabelName("k"): model.LabelValue("3"),373model.LabelName("__meta_url"): model.LabelValue(ts.URL),374},375Source: urlSource(ts.URL, 2),376},377},378{379{380Targets: []model.LabelSet{381{382model.AddressLabel: model.LabelValue("127.0.0.1"),383},384},385Labels: model.LabelSet{386model.LabelName("k"): model.LabelValue("1"),387model.LabelName("__meta_url"): model.LabelValue(ts.URL),388},389Source: urlSource(ts.URL, 0),390},391{392Targets: nil,393Labels: nil,394Source: urlSource(ts.URL, 1),395},396{397Targets: nil,398Labels: nil,399Source: urlSource(ts.URL, 2),400},401},402{403{404Targets: []model.LabelSet{405{406model.AddressLabel: model.LabelValue("127.0.0.2"),407},408},409Labels: model.LabelSet{410model.LabelName("k"): model.LabelValue("v"),411model.LabelName("__meta_url"): model.LabelValue(ts.URL),412},413Source: urlSource(ts.URL, 0),414},415{416Targets: []model.LabelSet{417{418model.AddressLabel: model.LabelValue("127.0.0.3"),419},420},421Labels: model.LabelSet{422model.LabelName("k"): model.LabelValue("vv"),423model.LabelName("__meta_url"): model.LabelValue(ts.URL),424},425Source: urlSource(ts.URL, 1),426},427},428},429},430}431
432cfg := SDConfig{433HTTPClientConfig: config.DefaultHTTPClientConfig,434URL: ts.URL,435RefreshInterval: model.Duration(1 * time.Second),436}437
438reg := prometheus.NewRegistry()439refreshMetrics := discovery.NewRefreshMetrics(reg)440defer refreshMetrics.Unregister()441metrics := cfg.NewDiscovererMetrics(reg, refreshMetrics)442require.NoError(t, metrics.Register())443defer metrics.Unregister()444
445d, err := NewDiscovery(&cfg, log.NewNopLogger(), nil, metrics)446require.NoError(t, err)447for _, test := range cases {448ctx := context.Background()449for i, res := range test.responses {450stubResponse = res451tgs, err := d.Refresh(ctx)452require.NoError(t, err)453require.Equal(t, test.expectedTargets[i], tgs)454}455}456}
457