improvement(go.d): add bearer_token_file to request cfg (#20476)
Ilya Mashchenko committed
Jun 13, 2025 at 14:32 UTC
1d5385d150be823a8b9c5a7264cb3476a5aeec47
128 files changed
+957
-141
src/go/plugin/go.d/collector/activemq/testdata/config.json
+1
@@ -15,6 +15,7 @@
15
},
16
"username": "ok",
17
"password": "ok",
18
+ "bearer_token_file": "ok",
19
"proxy_url": "ok",
20
"proxy_username": "ok",
21
"proxy_password": "ok",
src/go/plugin/go.d/collector/activemq/testdata/config.yaml
+1
@@ -13,6 +13,7 @@ headers:
13
ok: "ok"
14
username: "ok"
15
password: "ok"
16
+bearer_token_file: "ok"
17
proxy_url: "ok"
18
proxy_username: "ok"
19
proxy_password: "ok"
src/go/plugin/go.d/collector/apache/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/apache/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/bind/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/bind/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/cassandra/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/cassandra/testdata/config.yaml
+1
@@ -9,6 +9,7 @@ headers:
9
ok: "ok"
10
username: "ok"
11
password: "ok"
12
+bearer_token_file: "ok"
13
proxy_url: "ok"
14
proxy_username: "ok"
15
proxy_password: "ok"
src/go/plugin/go.d/collector/ceph/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/ceph/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/clickhouse/collect_system_async_metrics.go
+5
-2
@@ -22,7 +22,10 @@ where
22
`
23
24
func (c *Collector) collectSystemAsyncMetrics(mx map[string]int64) error {
25
- req, _ := web.NewHTTPRequest(c.RequestConfig)
25
+ req, err := web.NewHTTPRequest(c.RequestConfig)
26
+ if err != nil {
27
+ return err
28
+ }
29
req.URL.RawQuery = makeURLQuery(querySystemAsyncMetrics)
30
31
want := map[string]float64{
@@ -35,7 +38,7 @@ func (c *Collector) collectSystemAsyncMetrics(mx map[string]int64) error {
38
var metric string
39
var n int
40
38
- err := c.doHTTP(req, func(column, value string, lineEnd bool) {
41
+ err = c.doHTTP(req, func(column, value string, lineEnd bool) {
42
switch column {
43
case "metric":
44
metric = value
src/go/plugin/go.d/collector/clickhouse/collect_system_disks.go
+5
-2
@@ -26,7 +26,10 @@ type diskStats struct {
26
}
27
28
func (c *Collector) collectSystemDisks(mx map[string]int64) error {
29
- req, _ := web.NewHTTPRequest(c.RequestConfig)
29
+ req, err := web.NewHTTPRequest(c.RequestConfig)
30
+ if err != nil {
31
+ return err
32
+ }
33
req.URL.RawQuery = makeURLQuery(querySystemDisks)
34
35
seen := make(map[string]*diskStats)
@@ -42,7 +45,7 @@ func (c *Collector) collectSystemDisks(mx map[string]int64) error {
45
46
var name string
47
45
- err := c.doHTTP(req, func(column, value string, lineEnd bool) {
48
+ err = c.doHTTP(req, func(column, value string, lineEnd bool) {
49
switch column {
50
case "name":
51
name = value
src/go/plugin/go.d/collector/clickhouse/collect_system_events.go
+5
-2
@@ -18,14 +18,17 @@ FROM
18
`
19
20
func (c *Collector) collectSystemEvents(mx map[string]int64) error {
21
- req, _ := web.NewHTTPRequest(c.RequestConfig)
21
+ req, err := web.NewHTTPRequest(c.RequestConfig)
22
+ if err != nil {
23
+ return err
24
+ }
25
req.URL.RawQuery = makeURLQuery(querySystemEvents)
26
27
px := "events_"
28
var event string
29
var n int
30
28
- err := c.doHTTP(req, func(column, value string, lineEnd bool) {
31
+ err = c.doHTTP(req, func(column, value string, lineEnd bool) {
32
switch column {
33
case "event":
34
event = value
src/go/plugin/go.d/collector/clickhouse/collect_system_metrics.go
+5
-2
@@ -18,14 +18,17 @@ FROM
18
`
19
20
func (c *Collector) collectSystemMetrics(mx map[string]int64) error {
21
- req, _ := web.NewHTTPRequest(c.RequestConfig)
21
+ req, err := web.NewHTTPRequest(c.RequestConfig)
22
+ if err != nil {
23
+ return err
24
+ }
25
req.URL.RawQuery = makeURLQuery(querySystemMetrics)
26
27
px := "metrics_"
28
var metric string
29
var n int
30
28
- err := c.doHTTP(req, func(column, value string, lineEnd bool) {
31
+ err = c.doHTTP(req, func(column, value string, lineEnd bool) {
32
switch column {
33
case "metric":
34
metric = value
src/go/plugin/go.d/collector/clickhouse/collect_system_parts.go
+5
-2
@@ -34,7 +34,10 @@ type tableStats struct {
34
}
35
36
func (c *Collector) collectSystemParts(mx map[string]int64) error {
37
- req, _ := web.NewHTTPRequest(c.RequestConfig)
37
+ req, err := web.NewHTTPRequest(c.RequestConfig)
38
+ if err != nil {
39
+ return err
40
+ }
41
req.URL.RawQuery = makeURLQuery(querySystemParts)
42
43
seen := make(map[string]*tableStats)
@@ -51,7 +54,7 @@ func (c *Collector) collectSystemParts(mx map[string]int64) error {
54
55
var database, table string
56
54
- err := c.doHTTP(req, func(column, value string, lineEnd bool) {
57
+ err = c.doHTTP(req, func(column, value string, lineEnd bool) {
58
switch column {
59
case "database":
60
database = value
src/go/plugin/go.d/collector/clickhouse/collect_system_processes.go
+4
-1
@@ -16,7 +16,10 @@ FROM
16
`
17
18
func (c *Collector) collectLongestRunningQueryTime(mx map[string]int64) error {
19
- req, _ := web.NewHTTPRequest(c.RequestConfig)
19
+ req, err := web.NewHTTPRequest(c.RequestConfig)
20
+ if err != nil {
21
+ return err
22
+ }
23
req.URL.RawQuery = makeURLQuery(queryLongestQueryTime)
24
25
return c.doHTTP(req, func(column, value string, lineEnd bool) {
src/go/plugin/go.d/collector/clickhouse/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/clickhouse/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/cockroachdb/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/cockroachdb/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/consul/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/consul/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/coredns/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/coredns/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/couchbase/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/couchbase/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/couchdb/collect.go
+4
-1
@@ -201,7 +201,10 @@ func findMaxMQSize(MessageQueues map[string]any) int64 {
201
}
202
203
func (c *Collector) pingCouchDB() error {
204
- req, _ := web.NewHTTPRequest(c.RequestConfig)
204
+ req, err := web.NewHTTPRequest(c.RequestConfig)
205
+ if err != nil {
206
+ return err
207
+ }
208
209
var info struct{ Couchdb string }
210
src/go/plugin/go.d/collector/couchdb/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/couchdb/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/dnsdist/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/dnsdist/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/docker_engine/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/docker_engine/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/dockerhub/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/dockerhub/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/elasticsearch/collect.go
+4
-1
@@ -212,7 +212,10 @@ func (c *Collector) scrapeLocalIndicesStats(ms *esMetrics) {
212
}
213
214
func (c *Collector) getClusterName() (string, error) {
215
- req, _ := web.NewHTTPRequest(c.RequestConfig)
215
+ req, err := web.NewHTTPRequest(c.RequestConfig)
216
+ if err != nil {
217
+ return "", err
218
+ }
219
220
var info struct {
221
ClusterName string `json:"cluster_name"`
src/go/plugin/go.d/collector/elasticsearch/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/elasticsearch/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/envoy/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/envoy/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/fluentd/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/fluentd/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/geth/testdata/config.json
+1
@@ -8,6 +8,7 @@
8
},
9
"username": "ok",
10
"password": "ok",
11
+ "bearer_token_file": "ok",
12
"proxy_url": "ok",
13
"proxy_username": "ok",
14
"proxy_password": "ok",
src/go/plugin/go.d/collector/geth/testdata/config.yaml
+1
@@ -6,6 +6,7 @@ headers:
6
ok: "ok"
7
username: "ok"
8
password: "ok"
9
+bearer_token_file: "ok"
10
proxy_url: "ok"
11
proxy_username: "ok"
12
proxy_password: "ok"
src/go/plugin/go.d/collector/haproxy/testdata/config.json
+1
@@ -9,6 +9,7 @@
9
},
10
"username": "ok",
11
"password": "ok",
12
+ "bearer_token_file": "ok",
13
"proxy_url": "ok",
14
"proxy_username": "ok",
15
"proxy_password": "ok",
src/go/plugin/go.d/collector/haproxy/testdata/config.yaml
+1
@@ -7,6 +7,7 @@ headers:
7
ok: "ok"
8
username: "ok"
9
password: "ok"
10
+bearer_token_file: "ok"
11
proxy_url: "ok"
12
proxy_username: "ok"
13
proxy_password: "ok"
src/go/plugin/go.d/collector/hdfs/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/hdfs/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/httpcheck/testdata/config.json
+1
@@ -9,6 +9,7 @@
9
},
10
"username": "ok",
11
"password": "ok",
12
+ "bearer_token_file": "ok",
13
"proxy_url": "ok",
14
"proxy_username": "ok",
15
"proxy_password": "ok",
src/go/plugin/go.d/collector/httpcheck/testdata/config.yaml
+1
@@ -7,6 +7,7 @@ headers:
7
ok: "ok"
8
username: "ok"
9
password: "ok"
10
+bearer_token_file: "ok"
11
proxy_url: "ok"
12
proxy_username: "ok"
13
proxy_password: "ok"
src/go/plugin/go.d/collector/icecast/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/icecast/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/ipfs/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/ipfs/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/k8s_kubelet/collector.go
+3
-8
@@ -35,14 +35,14 @@ func New() *Collector {
35
Config: Config{
36
HTTPConfig: web.HTTPConfig{
37
RequestConfig: web.RequestConfig{
38
- URL: "http://127.0.0.1:10255/metrics",
39
- Headers: make(map[string]string),
38
+ URL: "http://127.0.0.1:10255/metrics",
39
+ Headers: make(map[string]string),
40
+ BearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token",
41
},
42
ClientConfig: web.ClientConfig{
43
Timeout: confopt.Duration(time.Second),
44
},
45
},
45
- TokenPath: "/var/run/secrets/kubernetes.io/serviceaccount/token",
46
},
47
48
charts: charts.Copy(),
@@ -55,7 +55,6 @@ type Config struct {
55
UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"`
56
AutoDetectionRetry int `yaml:"autodetection_retry,omitempty" json:"autodetection_retry"`
57
web.HTTPConfig `yaml:",inline" json:""`
58
- TokenPath string `yaml:"token_path,omitempty" json:"token_path"`
58
}
59
60
type Collector struct {
@@ -84,10 +83,6 @@ func (c *Collector) Init(context.Context) error {
83
}
84
c.prom = prom
85
87
- if tok := c.initAuthToken(); tok != "" {
88
- c.RequestConfig.Headers["Authorization"] = "Bearer " + tok
89
- }
90
-
86
return nil
87
}
88
src/go/plugin/go.d/collector/k8s_kubelet/collector_test.go
+2
-8
@@ -50,14 +50,6 @@ func TestCollector_Init(t *testing.T) {
50
assert.NoError(t, New().Init(context.Background()))
51
}
52
53
-func TestCollector_Init_ReadServiceAccountToken(t *testing.T) {
54
- collr := New()
55
- collr.TokenPath = "testdata/token.txt"
56
-
57
- assert.NoError(t, collr.Init(context.Background()))
58
- assert.Equal(t, "Bearer "+string(dataServiceAccountToken), collr.RequestConfig.Headers["Authorization"])
59
-}
60
-
53
func TestCollector_InitErrorOnCreatingClientWrongTLSCA(t *testing.T) {
54
collr := New()
55
collr.ClientConfig.TLSConfig.TLSCA = "testdata/tls"
@@ -74,6 +66,7 @@ func TestCollector_Check(t *testing.T) {
66
defer ts.Close()
67
68
collr := New()
69
+ collr.BearerTokenFile = ""
70
collr.URL = ts.URL + "/metrics"
71
require.NoError(t, collr.Init(context.Background()))
72
assert.NoError(t, collr.Check(context.Background()))
@@ -95,6 +88,7 @@ func TestCollector_Collect(t *testing.T) {
88
defer ts.Close()
89
90
collr := New()
91
+ collr.BearerTokenFile = ""
92
collr.URL = ts.URL + "/metrics"
93
require.NoError(t, collr.Init(context.Background()))
94
require.NoError(t, collr.Check(context.Background()))
src/go/plugin/go.d/collector/k8s_kubelet/init.go
-9
@@ -4,7 +4,6 @@ package k8s_kubelet
4
5
import (
6
"errors"
7
- "os"
7
8
"github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/prometheus"
9
"github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
@@ -17,14 +16,6 @@ func (c *Collector) validateConfig() error {
16
return nil
17
}
18
20
-func (c *Collector) initAuthToken() string {
21
- bs, err := os.ReadFile(c.TokenPath)
22
- if err != nil {
23
- c.Warningf("error on reading service account token from '%s': %v", c.TokenPath, err)
24
- }
25
- return string(bs)
26
-}
27
-
19
func (c *Collector) initPrometheusClient() (prometheus.Prometheus, error) {
20
httpClient, err := web.NewHTTPClient(c.ClientConfig)
21
if err != nil {
src/go/plugin/go.d/collector/k8s_kubelet/testdata/config.json
+2
-2
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
@@ -19,6 +20,5 @@
20
"tls_cert": "ok",
21
"tls_key": "ok",
22
"tls_skip_verify": true,
22
- "force_http2": true,
23
- "token_path": "ok"
23
+ "force_http2": true
24
}
src/go/plugin/go.d/collector/k8s_kubelet/testdata/config.yaml
+2
-2
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
@@ -17,5 +18,4 @@ tls_ca: "ok"
18
tls_cert: "ok"
19
tls_key: "ok"
20
tls_skip_verify: yes
20
-force_http2: yes
21
-token_path: "ok"
21
+force_http2: yes
\ No newline at end of file
src/go/plugin/go.d/collector/k8s_kubeproxy/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/k8s_kubeproxy/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/lighttpd/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/lighttpd/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/logstash/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/logstash/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/maxscale/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/maxscale/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/monit/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/monit/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/nats/testdata/config.json
+1
@@ -11,6 +11,7 @@
11
},
12
"username": "ok",
13
"password": "ok",
14
+ "bearer_token_file": "ok",
15
"proxy_url": "ok",
16
"proxy_username": "ok",
17
"proxy_password": "ok",
src/go/plugin/go.d/collector/nats/testdata/config.yaml
+1
@@ -9,6 +9,7 @@ headers:
9
ok: "ok"
10
username: "ok"
11
password: "ok"
12
+bearer_token_file: "ok"
13
proxy_url: "ok"
14
proxy_username: "ok"
15
proxy_password: "ok"
src/go/plugin/go.d/collector/nginx/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/nginx/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/nginxplus/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/nginxplus/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/nginxunit/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/nginxunit/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/nginxvts/collect.go
+4
-1
@@ -40,7 +40,10 @@ func (c *Collector) collectServerZones(collected map[string]any, ms *vtsMetrics)
40
}
41
42
func (c *Collector) scapeVTS() (*vtsMetrics, error) {
43
- req, _ := web.NewHTTPRequest(c.RequestConfig)
43
+ req, err := web.NewHTTPRequest(c.RequestConfig)
44
+ if err != nil {
45
+ return nil, err
46
+ }
47
48
var total vtsMetrics
49
if err := web.DoHTTP(c.httpClient).RequestJSON(req, &total); err != nil {
src/go/plugin/go.d/collector/nginxvts/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/nginxvts/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/phpdaemon/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/phpdaemon/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/phpfpm/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/phpfpm/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/pihole/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/pihole/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/powerdns/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/powerdns/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/powerdns_recursor/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/powerdns_recursor/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/prometheus/collector.go
-1
@@ -55,7 +55,6 @@ type Config struct {
55
Name string `yaml:"name,omitempty" json:"name"`
56
Application string `yaml:"app,omitempty" json:"app"`
57
LabelPrefix string `yaml:"label_prefix,omitempty" json:"label_prefix"`
58
- BearerTokenFile string `yaml:"bearer_token_file,omitempty" json:"bearer_token_file"`
58
Selector selector.Expr `yaml:"selector,omitempty" json:"selector"`
59
ExpectedPrefix string `yaml:"expected_prefix,omitempty" json:"expected_prefix"`
60
MaxTS int `yaml:"max_time_series" json:"max_time_series"`
src/go/plugin/go.d/collector/prometheus/init.go
-8
@@ -5,7 +5,6 @@ package prometheus
5
import (
6
"errors"
7
"fmt"
8
- "os"
8
9
"github.com/netdata/netdata/go/plugins/pkg/matcher"
10
"github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/prometheus"
@@ -26,13 +25,6 @@ func (c *Collector) initPrometheusClient() (prometheus.Prometheus, error) {
25
}
26
27
req := c.RequestConfig.Copy()
29
- if c.BearerTokenFile != "" {
30
- token, err := os.ReadFile(c.BearerTokenFile)
31
- if err != nil {
32
- return nil, fmt.Errorf("bearer token file: %v", err)
33
- }
34
- req.Headers["Authorization"] = "Bearer " + string(token)
35
- }
28
29
sr, err := c.Selector.Parse()
30
if err != nil {
src/go/plugin/go.d/collector/prometheus/testdata/config.json
+1
-1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
@@ -23,7 +24,6 @@
24
"name": "ok",
25
"app": "ok",
26
"label_prefix": "ok",
26
- "bearer_token_file": "ok",
27
"selector": {
28
"allow": [
29
"ok"
src/go/plugin/go.d/collector/prometheus/testdata/config.yaml
+1
-1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
@@ -21,7 +22,6 @@ force_http2: yes
22
name: "ok"
23
app: "ok"
24
label_prefix: "ok"
24
-bearer_token_file: "ok"
25
selector:
26
allow:
27
- "ok"
src/go/plugin/go.d/collector/pulsar/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/pulsar/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/puppet/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/puppet/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/rabbitmq/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/rabbitmq/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/riakkv/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/riakkv/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/rspamd/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/rspamd/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/scaleio/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/scaleio/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/squid/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/squid/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/tengine/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/tengine/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/tomcat/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/tomcat/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/traefik/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/traefik/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/typesense/testdata/config.json
+1
@@ -11,6 +11,7 @@
11
},
12
"username": "ok",
13
"password": "ok",
14
+ "bearer_token_file": "ok",
15
"proxy_url": "ok",
16
"proxy_username": "ok",
17
"proxy_password": "ok",
src/go/plugin/go.d/collector/typesense/testdata/config.yaml
+1
@@ -9,6 +9,7 @@ headers:
9
ok: "ok"
10
username: "ok"
11
password: "ok"
12
+bearer_token_file: "ok"
13
proxy_url: "ok"
14
proxy_username: "ok"
15
proxy_password: "ok"
src/go/plugin/go.d/collector/vcsa/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/vcsa/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/vernemq/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/vernemq/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/vsphere/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/vsphere/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/collector/yugabytedb/testdata/config.json
+1
@@ -10,6 +10,7 @@
10
},
11
"username": "ok",
12
"password": "ok",
13
+ "bearer_token_file": "ok",
14
"proxy_url": "ok",
15
"proxy_username": "ok",
16
"proxy_password": "ok",
src/go/plugin/go.d/collector/yugabytedb/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8
ok: "ok"
9
username: "ok"
10
password: "ok"
11
+bearer_token_file: "ok"
12
proxy_url: "ok"
13
proxy_username: "ok"
14
proxy_password: "ok"
src/go/plugin/go.d/pkg/web/client_config.go
+3
-3
@@ -68,12 +68,12 @@ func NewHTTPClient(cfg ClientConfig) (*http.Client, error) {
68
func newHTTPTransport(cfg ClientConfig) (*http.Transport, error) {
69
tlsConfig, err := tlscfg.NewTLSConfig(cfg.TLSConfig)
70
if err != nil {
71
- return nil, fmt.Errorf("error on creating TLS config: %v", err)
71
+ return nil, fmt.Errorf("error on creating TLS config: %w", err)
72
}
73
74
if cfg.ProxyURL != "" {
75
if _, err := url.Parse(cfg.ProxyURL); err != nil {
76
- return nil, fmt.Errorf("error on parsing proxy URL '%s': %v", cfg.ProxyURL, err)
76
+ return nil, fmt.Errorf("error on parsing proxy URL '%s': %w", cfg.ProxyURL, err)
77
}
78
}
79
@@ -92,7 +92,7 @@ func newHTTPTransport(cfg ClientConfig) (*http.Transport, error) {
92
func newHTTP2Transport(cfg ClientConfig) (*http2Transport, error) {
93
tlsConfig, err := tlscfg.NewTLSConfig(cfg.TLSConfig)
94
if err != nil {
95
- return nil, fmt.Errorf("error on creating TLS config: %v", err)
95
+ return nil, fmt.Errorf("error on creating TLS config: %w", err)
96
}
97
98
d := &net.Dialer{Timeout: cfg.Timeout.Duration()}
src/go/plugin/go.d/pkg/web/client_config_test.go
+442
-7
@@ -3,23 +3,458 @@
3
package web
4
5
import (
6
+ "errors"
7
+ "net"
8
"net/http"
9
+ "net/http/httptest"
10
+ "net/url"
11
+ "os"
12
"testing"
13
"time"
14
15
+ "golang.org/x/net/http2"
16
+
17
"github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/confopt"
18
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/tlscfg"
19
20
"github.com/stretchr/testify/assert"
21
+ "github.com/stretchr/testify/require"
22
)
23
24
func TestNewHTTPClient(t *testing.T) {
16
- client, _ := NewHTTPClient(ClientConfig{
17
- Timeout: confopt.Duration(time.Second * 5),
18
- NotFollowRedirect: true,
19
- ProxyURL: "http://127.0.0.1:3128",
25
+ tests := map[string]struct {
26
+ config ClientConfig
27
+ validate func(t *testing.T, client *http.Client, cfg ClientConfig)
28
+ wantErr bool
29
+ errMsg string
30
+ }{
31
+ "default config": {
32
+ config: ClientConfig{},
33
+ validate: func(t *testing.T, client *http.Client, cfg ClientConfig) {
34
+ assert.Zero(t, client.Timeout)
35
+ assert.Nil(t, client.CheckRedirect)
36
+ assert.NotNil(t, client.Transport)
37
+
38
+ // Verify it's using http.Transport (not http2)
39
+ transport, ok := client.Transport.(*http.Transport)
40
+ assert.True(t, ok)
41
+ assert.NotNil(t, transport)
42
+ },
43
+ },
44
+ "with timeout": {
45
+ config: ClientConfig{
46
+ Timeout: confopt.Duration(time.Second * 5),
47
+ },
48
+ validate: func(t *testing.T, client *http.Client, cfg ClientConfig) {
49
+ assert.Equal(t, time.Second*5, client.Timeout)
50
+
51
+ transport, ok := client.Transport.(*http.Transport)
52
+ require.True(t, ok)
53
+ assert.Equal(t, time.Second*5, transport.TLSHandshakeTimeout)
54
+ },
55
+ },
56
+ "not follow redirect": {
57
+ config: ClientConfig{
58
+ NotFollowRedirect: true,
59
+ },
60
+ validate: func(t *testing.T, client *http.Client, cfg ClientConfig) {
61
+ assert.NotNil(t, client.CheckRedirect)
62
+
63
+ // Test the redirect function
64
+ err := client.CheckRedirect(nil, nil)
65
+ assert.Equal(t, ErrRedirectAttempted, err)
66
+ },
67
+ },
68
+ "with proxy URL": {
69
+ config: ClientConfig{
70
+ ProxyURL: "http://127.0.0.1:3128",
71
+ },
72
+ validate: func(t *testing.T, client *http.Client, cfg ClientConfig) {
73
+ transport, ok := client.Transport.(*http.Transport)
74
+ require.True(t, ok)
75
+ assert.NotNil(t, transport.Proxy)
76
+
77
+ // Test proxy function
78
+ req := httptest.NewRequest("GET", "http://example.com", nil)
79
+ proxyURL, err := transport.Proxy(req)
80
+ assert.NoError(t, err)
81
+ assert.Equal(t, "http://127.0.0.1:3128", proxyURL.String())
82
+ },
83
+ },
84
+ "invalid proxy URL": {
85
+ config: ClientConfig{
86
+ ProxyURL: "://invalid-url",
87
+ },
88
+ wantErr: true,
89
+ errMsg: "error on parsing proxy URL",
90
+ },
91
+ "empty proxy URL uses environment": {
92
+ config: ClientConfig{
93
+ ProxyURL: "",
94
+ },
95
+ validate: func(t *testing.T, client *http.Client, cfg ClientConfig) {
96
+ transport, ok := client.Transport.(*http.Transport)
97
+ require.True(t, ok)
98
+
99
+ // Set env var for testing
100
+ _ = os.Setenv("HTTP_PROXY", "http://env-proxy:8080")
101
+ defer func() { _ = os.Unsetenv("HTTP_PROXY") }()
102
+
103
+ req := httptest.NewRequest("GET", "http://example.com", nil)
104
+ proxyURL, err := transport.Proxy(req)
105
+ assert.NoError(t, err)
106
+ if proxyURL != nil {
107
+ assert.Equal(t, "http://env-proxy:8080", proxyURL.String())
108
+ }
109
+ },
110
+ },
111
+ "force HTTP2": {
112
+ config: ClientConfig{
113
+ ForceHTTP2: true,
114
+ },
115
+ validate: func(t *testing.T, client *http.Client, cfg ClientConfig) {
116
+ // Verify it's using http2Transport
117
+ transport, ok := client.Transport.(*http2Transport)
118
+ assert.True(t, ok)
119
+ assert.NotNil(t, transport)
120
+ assert.NotNil(t, transport.t2)
121
+ assert.NotNil(t, transport.t2c)
122
+ },
123
+ },
124
+ "with TLS config": {
125
+ config: ClientConfig{
126
+ TLSConfig: tlscfg.TLSConfig{
127
+ InsecureSkipVerify: true,
128
+ },
129
+ },
130
+ validate: func(t *testing.T, client *http.Client, cfg ClientConfig) {
131
+ transport, ok := client.Transport.(*http.Transport)
132
+ require.True(t, ok)
133
+ assert.NotNil(t, transport.TLSClientConfig)
134
+ assert.True(t, transport.TLSClientConfig.InsecureSkipVerify)
135
+ },
136
+ },
137
+ "invalid TLS config": {
138
+ config: ClientConfig{
139
+ TLSConfig: tlscfg.TLSConfig{
140
+ TLSCA: "/non/existent/ca.pem",
141
+ TLSCert: "/non/existent/cert.pem",
142
+ TLSKey: "/non/existent/key.pem",
143
+ },
144
+ },
145
+ wantErr: true,
146
+ errMsg: "error on creating TLS config",
147
+ },
148
+ "full config": {
149
+ config: ClientConfig{
150
+ Timeout: confopt.Duration(time.Second * 10),
151
+ NotFollowRedirect: true,
152
+ ProxyURL: "http://proxy:8080",
153
+ TLSConfig: tlscfg.TLSConfig{
154
+ InsecureSkipVerify: true,
155
+ },
156
+ },
157
+ validate: func(t *testing.T, client *http.Client, cfg ClientConfig) {
158
+ assert.Equal(t, time.Second*10, client.Timeout)
159
+ assert.NotNil(t, client.CheckRedirect)
160
+
161
+ transport, ok := client.Transport.(*http.Transport)
162
+ require.True(t, ok)
163
+ assert.True(t, transport.TLSClientConfig.InsecureSkipVerify)
164
+ assert.NotNil(t, transport.Proxy)
165
+ },
166
+ },
167
+ "HTTP2 with TLS config": {
168
+ config: ClientConfig{
169
+ ForceHTTP2: true,
170
+ TLSConfig: tlscfg.TLSConfig{
171
+ InsecureSkipVerify: true,
172
+ },
173
+ },
174
+ validate: func(t *testing.T, client *http.Client, cfg ClientConfig) {
175
+ transport, ok := client.Transport.(*http2Transport)
176
+ require.True(t, ok)
177
+ assert.True(t, transport.t2.TLSClientConfig.InsecureSkipVerify)
178
+ assert.True(t, transport.t2c.TLSClientConfig.InsecureSkipVerify)
179
+ },
180
+ },
181
+ }
182
+
183
+ for name, test := range tests {
184
+ t.Run(name, func(t *testing.T) {
185
+ client, err := NewHTTPClient(test.config)
186
+
187
+ if test.wantErr {
188
+ assert.Error(t, err)
189
+ if test.errMsg != "" {
190
+ assert.Contains(t, err.Error(), test.errMsg)
191
+ }
192
+ assert.Nil(t, client)
193
+ return
194
+ }
195
+
196
+ require.NoError(t, err)
197
+ require.NotNil(t, client)
198
+
199
+ if test.validate != nil {
200
+ test.validate(t, client, test.config)
201
+ }
202
+ })
203
+ }
204
+}
205
+
206
+func TestHTTP2Transport_RoundTrip(t *testing.T) {
207
+ // Test that http2Transport can be created and has the expected structure
208
+ cfg := ClientConfig{
209
+ ForceHTTP2: true,
210
+ TLSConfig: tlscfg.TLSConfig{
211
+ InsecureSkipVerify: true,
212
+ },
213
+ }
214
+
215
+ client, err := NewHTTPClient(cfg)
216
+ require.NoError(t, err)
217
+
218
+ // Verify the transport is http2Transport
219
+ transport, ok := client.Transport.(*http2Transport)
220
+ require.True(t, ok)
221
+ assert.NotNil(t, transport.t2)
222
+ assert.NotNil(t, transport.t2c)
223
+
224
+ // Note: We can't easily test actual HTTP/2 communication without setting up
225
+ // proper HTTP/2 servers, which httptest doesn't support directly.
226
+ // The integration test with regular servers is sufficient for basic functionality.
227
+}
228
+
229
+func TestHTTP2Transport_CloseIdleConnections(t *testing.T) {
230
+ transport := &http2Transport{
231
+ t2: &http2.Transport{},
232
+ t2c: &http2.Transport{},
233
+ }
234
+
235
+ // This should not panic
236
+ assert.NotPanics(t, func() {
237
+ transport.CloseIdleConnections()
238
})
239
+}
240
+
241
+func TestProxyFunc(t *testing.T) {
242
+ tests := map[string]struct {
243
+ proxyURL string
244
+ envProxy string
245
+ validate func(t *testing.T, proxyFunc func(*http.Request) (*url.URL, error))
246
+ }{
247
+ "empty proxy URL uses environment": {
248
+ proxyURL: "",
249
+ envProxy: "http://env-proxy:8080",
250
+ validate: func(t *testing.T, proxyFunc func(*http.Request) (*url.URL, error)) {
251
+ _ = os.Setenv("HTTP_PROXY", "http://env-proxy:8080")
252
+ defer func() { _ = os.Unsetenv("HTTP_PROXY") }()
253
+
254
+ req := httptest.NewRequest("GET", "http://example.com", nil)
255
+ proxyURL, err := proxyFunc(req)
256
+ assert.NoError(t, err)
257
+ if proxyURL != nil {
258
+ assert.Equal(t, "http://env-proxy:8080", proxyURL.String())
259
+ }
260
+ },
261
+ },
262
+ "specific proxy URL": {
263
+ proxyURL: "http://specific-proxy:3128",
264
+ validate: func(t *testing.T, proxyFunc func(*http.Request) (*url.URL, error)) {
265
+ req := httptest.NewRequest("GET", "http://example.com", nil)
266
+ proxyURL, err := proxyFunc(req)
267
+ assert.NoError(t, err)
268
+ assert.Equal(t, "http://specific-proxy:3128", proxyURL.String())
269
+ },
270
+ },
271
+ "proxy URL with auth": {
272
+ proxyURL: "http://user:pass@proxy:3128",
273
+ validate: func(t *testing.T, proxyFunc func(*http.Request) (*url.URL, error)) {
274
+ req := httptest.NewRequest("GET", "http://example.com", nil)
275
+ proxyURL, err := proxyFunc(req)
276
+ assert.NoError(t, err)
277
+ assert.Equal(t, "http://user:pass@proxy:3128", proxyURL.String())
278
+ assert.Equal(t, "user", proxyURL.User.Username())
279
+ pass, _ := proxyURL.User.Password()
280
+ assert.Equal(t, "pass", pass)
281
+ },
282
+ },
283
+ "https proxy URL": {
284
+ proxyURL: "https://secure-proxy:443",
285
+ validate: func(t *testing.T, proxyFunc func(*http.Request) (*url.URL, error)) {
286
+ req := httptest.NewRequest("GET", "http://example.com", nil)
287
+ proxyURL, err := proxyFunc(req)
288
+ assert.NoError(t, err)
289
+ assert.Equal(t, "https://secure-proxy:443", proxyURL.String())
290
+ },
291
+ },
292
+ }
293
+
294
+ for name, test := range tests {
295
+ t.Run(name, func(t *testing.T) {
296
+ fn := proxyFunc(test.proxyURL)
297
+ assert.NotNil(t, fn)
298
+
299
+ if test.validate != nil {
300
+ test.validate(t, fn)
301
+ }
302
+ })
303
+ }
304
+}
305
+
306
+func TestRedirectFunc(t *testing.T) {
307
+ tests := map[string]struct {
308
+ notFollow bool
309
+ wantErr error
310
+ }{
311
+ "follow redirects": {
312
+ notFollow: false,
313
+ wantErr: nil,
314
+ },
315
+ "not follow redirects": {
316
+ notFollow: true,
317
+ wantErr: ErrRedirectAttempted,
318
+ },
319
+ }
320
+
321
+ for name, test := range tests {
322
+ t.Run(name, func(t *testing.T) {
323
+ fn := redirectFunc(test.notFollow)
324
22
- assert.IsType(t, (*http.Client)(nil), client)
23
- assert.Equal(t, time.Second*5, client.Timeout)
24
- assert.NotNil(t, client.CheckRedirect)
325
+ if test.wantErr != nil {
326
+ assert.NotNil(t, fn)
327
+ err := fn(nil, nil)
328
+ assert.Equal(t, test.wantErr, err)
329
+ } else {
330
+ assert.Nil(t, fn)
331
+ }
332
+ })
333
+ }
334
+}
335
+
336
+func TestClientIntegration(t *testing.T) {
337
+ // Create a test server with various behaviors
338
+ redirectCount := 0
339
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
340
+ switch r.URL.Path {
341
+ case "/redirect":
342
+ redirectCount++
343
+ http.Redirect(w, r, "/final", http.StatusFound)
344
+ case "/final":
345
+ _, _ = w.Write([]byte("final destination"))
346
+ case "/timeout":
347
+ time.Sleep(time.Second * 2)
348
+ _, _ = w.Write([]byte("too late"))
349
+ default:
350
+ _, _ = w.Write([]byte("default response"))
351
+ }
352
+ }))
353
+ defer server.Close()
354
+
355
+ t.Run("follow redirects", func(t *testing.T) {
356
+ client, err := NewHTTPClient(ClientConfig{
357
+ NotFollowRedirect: false,
358
+ })
359
+ require.NoError(t, err)
360
+
361
+ resp, err := client.Get(server.URL + "/redirect")
362
+ require.NoError(t, err)
363
+ defer func() { _ = resp.Body.Close() }()
364
+
365
+ assert.Equal(t, "/final", resp.Request.URL.Path)
366
+ })
367
+
368
+ t.Run("not follow redirects", func(t *testing.T) {
369
+ client, err := NewHTTPClient(ClientConfig{
370
+ NotFollowRedirect: true,
371
+ })
372
+ require.NoError(t, err)
373
+
374
+ _, err = client.Get(server.URL + "/redirect")
375
+ assert.Error(t, err)
376
+
377
+ // Check if error contains redirect indication
378
+ urlErr, ok := err.(*url.Error)
379
+ if ok {
380
+ assert.Equal(t, ErrRedirectAttempted, urlErr.Err)
381
+ }
382
+ })
383
+
384
+ t.Run("timeout", func(t *testing.T) {
385
+ client, err := NewHTTPClient(ClientConfig{
386
+ Timeout: confopt.Duration(time.Millisecond * 500),
387
+ })
388
+ require.NoError(t, err)
389
+
390
+ _, err = client.Get(server.URL + "/timeout")
391
+ assert.Error(t, err)
392
+
393
+ var netErr net.Error
394
+ if errors.As(err, &netErr) {
395
+ assert.True(t, netErr.Timeout())
396
+ }
397
+ })
398
+}
399
+
400
+func TestTransportWithDifferentSchemes(t *testing.T) {
401
+ // Test that regular transport handles both http and https
402
+ client, err := NewHTTPClient(ClientConfig{
403
+ TLSConfig: tlscfg.TLSConfig{
404
+ InsecureSkipVerify: true,
405
+ },
406
+ })
407
+ require.NoError(t, err)
408
+
409
+ // HTTP server
410
+ httpServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
411
+ _, _ = w.Write([]byte("http"))
412
+ }))
413
+ defer httpServer.Close()
414
+
415
+ // HTTPS server
416
+ httpsServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
417
+ _, _ = w.Write([]byte("https"))
418
+ }))
419
+ defer httpsServer.Close()
420
+
421
+ // Test HTTP
422
+ resp, err := client.Get(httpServer.URL)
423
+ require.NoError(t, err)
424
+ _ = resp.Body.Close()
425
+
426
+ // Test HTTPS
427
+ resp, err = client.Get(httpsServer.URL)
428
+ require.NoError(t, err)
429
+ _ = resp.Body.Close()
430
+}
431
+
432
+func TestHTTP2TransportStructure(t *testing.T) {
433
+ // Test the http2Transport structure and methods
434
+ transport := &http2Transport{
435
+ t2: &http2.Transport{},
436
+ t2c: &http2.Transport{AllowHTTP: true},
437
+ }
438
+
439
+ // Test HTTPS request routing
440
+ httpsReq := httptest.NewRequest("GET", "https://example.com", nil)
441
+ // Just verify it doesn't panic and routes to the correct transport
442
+ assert.NotPanics(t, func() {
443
+ // We can't actually execute the request without a server,
444
+ // but we can verify the routing logic
445
+ if httpsReq.URL.Scheme == "https" {
446
+ // Would use t2
447
+ assert.NotNil(t, transport.t2)
448
+ }
449
+ })
450
+
451
+ // Test HTTP request routing
452
+ httpReq := httptest.NewRequest("GET", "http://example.com", nil)
453
+ assert.NotPanics(t, func() {
454
+ if httpReq.URL.Scheme == "http" {
455
+ // Would use t2c
456
+ assert.NotNil(t, transport.t2c)
457
+ assert.True(t, transport.t2c.AllowHTTP)
458
+ }
459
+ })
460
}
src/go/plugin/go.d/pkg/web/request_config.go
+70
-7
@@ -8,10 +8,12 @@ import (
8
"io"
9
"net/http"
10
"net/url"
11
+ "os"
12
"strings"
13
14
"github.com/netdata/netdata/go/plugins/pkg/buildinfo"
15
"github.com/netdata/netdata/go/plugins/pkg/executable"
16
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/hostinfo"
17
)
18
19
// RequestConfig is the configuration of the HTTP request.
@@ -27,6 +29,11 @@ type RequestConfig struct {
29
// Password specifies the password for basic HTTPConfig authentication.
30
Password string `yaml:"password,omitempty" json:"password"`
31
32
+ // BearerTokenFile specifies the path to a file containing a bearer token
33
+ // to be used for HTTP authentication.
34
+ // The token is read from the file and included in the Authorization header as "Bearer <token>".
35
+ BearerTokenFile string `yaml:"bearer_token_file,omitempty" json:"bearer_token_file"`
36
+
37
// ProxyUsername specifies the username for basic HTTPConfig authentication.
38
// It is used to authenticate a user agent to a proxy server.
39
ProxyUsername string `yaml:"proxy_username,omitempty" json:"proxy_username"`
@@ -47,6 +54,10 @@ type RequestConfig struct {
54
55
// Copy makes a full copy of the RequestConfig.
56
func (r RequestConfig) Copy() RequestConfig {
57
+ if r.Headers == nil {
58
+ return r
59
+ }
60
+
61
headers := make(map[string]string, len(r.Headers))
62
for k, v := range r.Headers {
63
headers[k] = v
@@ -57,22 +68,27 @@ func (r RequestConfig) Copy() RequestConfig {
68
69
var userAgent = fmt.Sprintf("Netdata %s.plugin/%s", executable.Name, buildinfo.Version)
70
60
-// NewHTTPRequest returns a new *http.Requests given a RequestConfig configuration and an error if any.
71
+// NewHTTPRequest returns a new *http.Request given a RequestConfig configuration and an error if any.
72
func NewHTTPRequest(cfg RequestConfig) (*http.Request, error) {
73
var body io.Reader
74
if cfg.Body != "" {
75
body = strings.NewReader(cfg.Body)
76
}
77
67
- req, err := http.NewRequest(cfg.Method, cfg.URL, body)
78
+ method := cfg.Method
79
+ if method == "" {
80
+ method = http.MethodGet
81
+ }
82
+
83
+ req, err := http.NewRequest(method, cfg.URL, body)
84
if err != nil {
85
return nil, err
86
}
87
88
req.Header.Set("User-Agent", userAgent)
89
74
- if cfg.Username != "" || cfg.Password != "" {
75
- req.SetBasicAuth(cfg.Username, cfg.Password)
90
+ if err := setAuthentication(req, cfg); err != nil {
91
+ return nil, err
92
}
93
94
if cfg.ProxyUsername != "" && cfg.ProxyPassword != "" {
@@ -81,8 +97,8 @@ func NewHTTPRequest(cfg RequestConfig) (*http.Request, error) {
97
}
98
99
for k, v := range cfg.Headers {
84
- switch k {
85
- case "host", "Host":
100
+ switch strings.ToLower(k) {
101
+ case "host":
102
req.Host = v
103
default:
104
req.Header.Set(k, v)
@@ -92,18 +108,65 @@ func NewHTTPRequest(cfg RequestConfig) (*http.Request, error) {
108
return req, nil
109
}
110
111
+func setAuthentication(req *http.Request, cfg RequestConfig) error {
112
+ // Priority: Bearer Token > Basic Auth
113
+ switch {
114
+ case cfg.BearerTokenFile != "":
115
+ return setBearerTokenAuth(req, cfg.BearerTokenFile)
116
+ case cfg.Username != "" || cfg.Password != "":
117
+ req.SetBasicAuth(cfg.Username, cfg.Password)
118
+ }
119
+ return nil
120
+}
121
+
122
+func setBearerTokenAuth(req *http.Request, tokenFile string) error {
123
+ tokenBs, err := os.ReadFile(tokenFile)
124
+ if err != nil {
125
+ // Ignore K8s service account token errors when running outside the cluster
126
+ if strings.HasPrefix(tokenFile, "/var/run/secrets/") && !hostinfo.IsInsideK8sCluster() {
127
+ return nil
128
+ }
129
+ return fmt.Errorf("bearer token file: %w", err)
130
+ }
131
+
132
+ token := strings.TrimSpace(string(tokenBs))
133
+ if token == "" {
134
+ return fmt.Errorf("bearer token file is empty")
135
+ }
136
+
137
+ req.Header.Set("Authorization", "Bearer "+token)
138
+ return nil
139
+}
140
+
141
+// NewHTTPRequestWithPath creates a new HTTP request with the given path appended to the base URL.
142
func NewHTTPRequestWithPath(cfg RequestConfig, urlPath string) (*http.Request, error) {
143
+ // Make a copy to avoid modifying the original config
144
cfg = cfg.Copy()
145
146
+ // Join the paths properly
147
v, err := url.JoinPath(cfg.URL, urlPath)
148
if err != nil {
100
- return nil, fmt.Errorf("failed to join URL path: %v", err)
149
+ return nil, fmt.Errorf("failed to join URL path: %w", err)
150
}
151
cfg.URL = v
152
153
return NewHTTPRequest(cfg)
154
}
155
156
+// URLQuery creates a URL-encoded query string from a single key-value pair.
157
func URLQuery(key, value string) string {
158
return url.Values{key: []string{value}}.Encode()
159
}
160
+
161
+// URLQueryMulti creates a URL-encoded query string from multiple key-value pairs.
162
+func URLQueryMulti(params map[string]string) string {
163
+ if len(params) == 0 {
164
+ return ""
165
+ }
166
+
167
+ values := url.Values{}
168
+ for k, v := range params {
169
+ values.Set(k, v)
170
+ }
171
+ return values.Encode()
172
+}
src/go/plugin/go.d/pkg/web/request_config_test.go
+284
-70
@@ -4,7 +4,10 @@ package web
4
5
import (
6
"encoding/base64"
7
+ "io"
8
"net/http"
9
+ "os"
10
+ "path/filepath"
11
"strings"
12
"testing"
13
@@ -16,6 +19,7 @@ func TestRequest_Copy(t *testing.T) {
19
tests := map[string]struct {
20
orig RequestConfig
21
change func(req *RequestConfig)
22
+ verify func(t *testing.T, orig, copy RequestConfig)
23
}{
24
"change headers": {
25
orig: RequestConfig{
@@ -32,6 +36,34 @@ func TestRequest_Copy(t *testing.T) {
36
change: func(req *RequestConfig) {
37
req.Headers["header_key"] = "header_value"
38
},
39
+ verify: func(t *testing.T, orig, copy RequestConfig) {
40
+ assert.Equal(t, 1, len(orig.Headers))
41
+ assert.Equal(t, 2, len(copy.Headers))
42
+ },
43
+ },
44
+ "nil headers": {
45
+ orig: RequestConfig{
46
+ URL: "http://127.0.0.1:19999/api/v1/info",
47
+ },
48
+ change: func(req *RequestConfig) {
49
+ req.Headers = map[string]string{"new": "header"}
50
+ },
51
+ verify: func(t *testing.T, orig, copy RequestConfig) {
52
+ assert.Nil(t, orig.Headers)
53
+ assert.NotNil(t, copy.Headers)
54
+ },
55
+ },
56
+ "change URL": {
57
+ orig: RequestConfig{
58
+ URL: "http://example.com",
59
+ },
60
+ change: func(req *RequestConfig) {
61
+ req.URL = "http://changed.com"
62
+ },
63
+ verify: func(t *testing.T, orig, copy RequestConfig) {
64
+ assert.Equal(t, "http://example.com", orig.URL)
65
+ assert.Equal(t, "http://changed.com", copy.URL)
66
+ },
67
},
68
}
69
@@ -39,73 +71,188 @@ func TestRequest_Copy(t *testing.T) {
71
t.Run(name, func(t *testing.T) {
72
reqCopy := test.orig.Copy()
73
74
+ // Initial state should be equal
75
assert.Equal(t, test.orig, reqCopy)
76
+
77
+ // Apply changes
78
test.change(&reqCopy)
79
+
80
+ // Verify changes don't affect original
81
assert.NotEqual(t, test.orig, reqCopy)
82
+
83
+ // Run custom verification if provided
84
+ if test.verify != nil {
85
+ test.verify(t, test.orig, reqCopy)
86
+ }
87
})
88
}
89
}
90
91
func TestNewHTTPRequest(t *testing.T) {
92
+ // Create a temporary file for bearer token test
93
+ tmpDir := t.TempDir()
94
+ bearerTokenFile := filepath.Join(tmpDir, "token")
95
+ err := os.WriteFile(bearerTokenFile, []byte("test-bearer-token"), 0644)
96
+ require.NoError(t, err)
97
+
98
tests := map[string]struct {
51
- req RequestConfig
52
- wantErr bool
99
+ req RequestConfig
100
+ validate func(t *testing.T, req *http.Request, cfg RequestConfig)
101
+ wantErr bool
102
+ errMsg string
103
}{
54
- "test url": {
104
+ "empty config": {
105
+ req: RequestConfig{},
106
+ validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
107
+ assert.Equal(t, "GET", req.Method)
108
+ assert.Equal(t, "", req.URL.String())
109
+ assert.NotEmpty(t, req.Header.Get("User-Agent"))
110
+ },
111
+ },
112
+ "full config": {
113
req: RequestConfig{
56
- URL: "http://127.0.0.1:19999/api/v1/info",
114
+ URL: "http://127.0.0.1:19999/api/v1/info",
115
+ Method: "POST",
116
+ Body: "test body content",
117
+ Username: "user",
118
+ Password: "pass",
119
+ ProxyUsername: "proxy_user",
120
+ ProxyPassword: "proxy_pass",
121
+ Headers: map[string]string{
122
+ "X-Custom-Header": "custom-value",
123
+ "Content-Type": "application/json",
124
+ },
125
+ },
126
+ validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
127
+ assert.Equal(t, cfg.URL, req.URL.String())
128
+ assert.Equal(t, cfg.Method, req.Method)
129
+
130
+ // Check body
131
+ body, err := io.ReadAll(req.Body)
132
+ require.NoError(t, err)
133
+ assert.Equal(t, cfg.Body, string(body))
134
+
135
+ // Check basic auth
136
+ user, pass, ok := req.BasicAuth()
137
+ assert.True(t, ok)
138
+ assert.Equal(t, cfg.Username, user)
139
+ assert.Equal(t, cfg.Password, pass)
140
+
141
+ // Check proxy auth
142
+ proxyAuth := req.Header.Get("Proxy-Authorization")
143
+ assert.NotEmpty(t, proxyAuth)
144
+ proxyUser, proxyPass, ok := parseBasicAuth(proxyAuth)
145
+ assert.True(t, ok)
146
+ assert.Equal(t, cfg.ProxyUsername, proxyUser)
147
+ assert.Equal(t, cfg.ProxyPassword, proxyPass)
148
+
149
+ // Check headers
150
+ for k, v := range cfg.Headers {
151
+ assert.Equal(t, v, req.Header.Get(k))
152
+ }
153
},
58
- wantErr: false,
154
},
60
- "test body": {
155
+ "bearer token authentication": {
156
req: RequestConfig{
62
- Body: "content",
157
+ URL: "http://example.com",
158
+ BearerTokenFile: bearerTokenFile,
159
+ },
160
+ validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
161
+ auth := req.Header.Get("Authorization")
162
+ assert.Equal(t, "Bearer test-bearer-token", auth)
163
},
64
- wantErr: false,
164
},
66
- "test method": {
165
+ "bearer token file not found": {
166
req: RequestConfig{
68
- Method: "POST",
167
+ URL: "http://example.com",
168
+ BearerTokenFile: "/non/existent/file",
169
},
70
- wantErr: false,
170
+ wantErr: true,
171
+ errMsg: "bearer token file",
172
},
72
- "test headers": {
173
+ "bearer token takes precedence over basic auth": {
174
req: RequestConfig{
74
- Headers: map[string]string{
75
- "X-Api-Key": "secret",
76
- },
175
+ URL: "http://example.com",
176
+ Username: "user",
177
+ Password: "pass",
178
+ BearerTokenFile: bearerTokenFile,
179
+ },
180
+ validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
181
+ // Should have bearer token, not basic auth
182
+ auth := req.Header.Get("Authorization")
183
+ assert.Equal(t, "Bearer test-bearer-token", auth)
184
+
185
+ // Basic auth should not be set
186
+ _, _, ok := req.BasicAuth()
187
+ assert.False(t, ok)
188
},
78
- wantErr: false,
189
},
80
- "test special headers (host)": {
190
+ "special headers - host lowercase": {
191
req: RequestConfig{
192
+ URL: "http://example.com",
193
Headers: map[string]string{
83
- "host": "Host",
194
+ "host": "custom-host.com",
195
},
196
},
86
- wantErr: false,
197
+ validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
198
+ assert.Equal(t, "custom-host.com", req.Host)
199
+ // host header should not be in req.Header
200
+ assert.Empty(t, req.Header.Get("host"))
201
+ },
202
},
88
- "test special headers (Host)": {
203
+ "special headers - Host uppercase": {
204
req: RequestConfig{
205
+ URL: "http://example.com",
206
Headers: map[string]string{
91
- "Host": "Host",
207
+ "Host": "custom-host.com",
208
},
209
},
94
- wantErr: false,
210
+ validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
211
+ assert.Equal(t, "custom-host.com", req.Host)
212
+ assert.Empty(t, req.Header.Get("Host"))
213
+ },
214
},
96
- "test username and password": {
215
+ "proxy auth without username": {
216
req: RequestConfig{
98
- Username: "username",
99
- Password: "password",
217
+ URL: "http://example.com",
218
+ ProxyPassword: "proxy_pass",
219
+ },
220
+ validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
221
+ // Proxy auth should not be set if username is missing
222
+ assert.Empty(t, req.Header.Get("Proxy-Authorization"))
223
},
101
- wantErr: false,
224
},
103
- "test proxy username and proxy password": {
225
+ "invalid URL": {
226
req: RequestConfig{
105
- ProxyUsername: "proxy_username",
106
- ProxyPassword: "proxy_password",
227
+ URL: "://invalid-url",
228
+ },
229
+ wantErr: true,
230
+ },
231
+ "empty body": {
232
+ req: RequestConfig{
233
+ URL: "http://example.com",
234
+ Body: "",
235
+ },
236
+ validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
237
+ assert.Nil(t, req.Body)
238
+ },
239
+ },
240
+ "default GET method": {
241
+ req: RequestConfig{
242
+ URL: "http://example.com",
243
+ },
244
+ validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
245
+ assert.Equal(t, "GET", req.Method)
246
+ },
247
+ },
248
+ "custom method": {
249
+ req: RequestConfig{
250
+ URL: "http://example.com",
251
+ Method: "DELETE",
252
+ },
253
+ validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
254
+ assert.Equal(t, "DELETE", req.Method)
255
},
108
- wantErr: false,
256
},
257
}
258
@@ -115,74 +262,141 @@ func TestNewHTTPRequest(t *testing.T) {
262
263
if test.wantErr {
264
assert.Error(t, err)
265
+ if test.errMsg != "" {
266
+ assert.Contains(t, err.Error(), test.errMsg)
267
+ }
268
assert.Nil(t, httpReq)
269
return
270
}
271
272
require.NoError(t, err)
273
require.NotNil(t, httpReq)
124
- require.IsType(t, (*http.Request)(nil), httpReq)
125
-
126
- assert.Equal(t, test.req.URL, httpReq.URL.String())
127
-
128
- if test.req.Body != "" {
129
- assert.NotNil(t, httpReq.Body)
130
- }
274
132
- if test.req.Username != "" || test.req.Password != "" {
133
- user, pass, ok := httpReq.BasicAuth()
134
- assert.True(t, ok)
135
- assert.Equal(t, test.req.Username, user)
136
- assert.Equal(t, test.req.Password, pass)
137
- }
138
-
139
- if test.req.Method != "" {
140
- assert.Equal(t, test.req.Method, httpReq.Method)
141
- }
142
-
143
- if test.req.ProxyUsername != "" || test.req.ProxyPassword != "" {
144
- user, pass, ok := parseBasicAuth(httpReq.Header.Get("Proxy-Authorization"))
145
- assert.True(t, ok)
146
- assert.Equal(t, test.req.ProxyUsername, user)
147
- assert.Equal(t, test.req.ProxyPassword, pass)
148
- }
149
-
150
- for k, v := range test.req.Headers {
151
- switch k {
152
- case "host", "Host":
153
- assert.Equal(t, httpReq.Host, v)
154
- default:
155
- assert.Equal(t, v, httpReq.Header.Get(k))
156
- }
275
+ if test.validate != nil {
276
+ test.validate(t, httpReq, test.req)
277
}
278
})
279
}
280
}
281
162
-func TestNewRequest(t *testing.T) {
282
+func TestNewHTTPRequestWithPath(t *testing.T) {
283
tests := map[string]struct {
164
- url string
284
+ config RequestConfig
285
path string
286
wantURL string
287
+ wantErr bool
288
+ errMsg string
289
}{
168
- "base url": {
169
- url: "http://127.0.0.1:65535",
290
+ "base url with path": {
291
+ config: RequestConfig{URL: "http://127.0.0.1:65535"},
292
path: "/bar",
293
wantURL: "http://127.0.0.1:65535/bar",
294
},
173
- "with path": {
174
- url: "http://127.0.0.1:65535/foo/",
295
+ "url with trailing slash": {
296
+ config: RequestConfig{URL: "http://127.0.0.1:65535/"},
297
+ path: "bar",
298
+ wantURL: "http://127.0.0.1:65535/bar",
299
+ },
300
+ "url with path and trailing slash": {
301
+ config: RequestConfig{URL: "http://127.0.0.1:65535/foo/"},
302
path: "/bar",
303
wantURL: "http://127.0.0.1:65535/foo/bar",
304
},
305
+ "url with path no trailing slash": {
306
+ config: RequestConfig{URL: "http://127.0.0.1:65535/foo"},
307
+ path: "bar",
308
+ wantURL: "http://127.0.0.1:65535/foo/bar",
309
+ },
310
+ "empty path": {
311
+ config: RequestConfig{URL: "http://example.com"},
312
+ path: "",
313
+ wantURL: "http://example.com",
314
+ },
315
+ "path with query params": {
316
+ config: RequestConfig{URL: "http://example.com"},
317
+ path: "/path?key=value",
318
+ wantURL: "http://example.com/path%3Fkey=value", // url.JoinPath correctly escapes special chars
319
+ },
320
+ "complex path": {
321
+ config: RequestConfig{URL: "http://example.com/api/v1"},
322
+ path: "../v2/endpoint",
323
+ wantURL: "http://example.com/api/v2/endpoint",
324
+ },
325
+ "preserve headers": {
326
+ config: RequestConfig{
327
+ URL: "http://example.com",
328
+ Headers: map[string]string{
329
+ "X-Custom": "value",
330
+ },
331
+ },
332
+ path: "/test",
333
+ wantURL: "http://example.com/test",
334
+ },
335
+ "invalid base URL": {
336
+ config: RequestConfig{URL: "://invalid"},
337
+ path: "/path",
338
+ wantErr: true,
339
+ },
340
}
341
342
for name, test := range tests {
343
t.Run(name, func(t *testing.T) {
182
- req, err := NewHTTPRequestWithPath(RequestConfig{URL: test.url}.Copy(), test.path)
183
- require.NoError(t, err)
344
+ // Store original headers count
345
+ originalHeadersCount := len(test.config.Headers)
346
+
347
+ req, err := NewHTTPRequestWithPath(test.config, test.path)
348
349
+ if test.wantErr {
350
+ assert.Error(t, err)
351
+ if test.errMsg != "" {
352
+ assert.Contains(t, err.Error(), test.errMsg)
353
+ }
354
+ assert.Nil(t, req)
355
+ return
356
+ }
357
+
358
+ require.NoError(t, err)
359
+ require.NotNil(t, req)
360
assert.Equal(t, test.wantURL, req.URL.String())
361
+
362
+ // Verify original config wasn't modified
363
+ assert.Equal(t, originalHeadersCount, len(test.config.Headers))
364
+ })
365
+ }
366
+}
367
+
368
+func TestURLQuery(t *testing.T) {
369
+ tests := map[string]struct {
370
+ key string
371
+ value string
372
+ want string
373
+ }{
374
+ "simple query": {
375
+ key: "foo",
376
+ value: "bar",
377
+ want: "foo=bar",
378
+ },
379
+ "empty value": {
380
+ key: "key",
381
+ value: "",
382
+ want: "key=",
383
+ },
384
+ "special characters": {
385
+ key: "key",
386
+ value: "value with spaces & special=chars",
387
+ want: "key=value+with+spaces+%26+special%3Dchars",
388
+ },
389
+ "unicode": {
390
+ key: "name",
391
+ value: "测试",
392
+ want: "name=%E6%B5%8B%E8%AF%95",
393
+ },
394
+ }
395
+
396
+ for name, test := range tests {
397
+ t.Run(name, func(t *testing.T) {
398
+ got := URLQuery(test.key, test.value)
399
+ assert.Equal(t, test.want, got)
400
})
401
}
402
}