[v7.5.x] HTTP Client: Introduce go-conntrack (#35321)

* Introduce go-conntrack into http transport

* Fix linting

* Add sanitize label name for datasource names

* Fix tests - add one to check missing datasource name

* Fix more tests

* Remove DialWithTracing()
This commit is contained in:
Dimitris Sotirakis
2021-06-07 16:17:18 +02:00
committed by GitHub
parent 39cbd2fc4e
commit 43e7e696e8
5 changed files with 48 additions and 10 deletions
+1
View File
@@ -63,6 +63,7 @@ require (
github.com/magefile/mage v1.11.0
github.com/mattn/go-isatty v0.0.12
github.com/mattn/go-sqlite3 v1.14.6
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f
github.com/opentracing/opentracing-go v1.2.0
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pkg/errors v0.9.1
+1 -1
View File
@@ -551,7 +551,7 @@ func TestDataSourceProxy_requestHandling(t *testing.T) {
}))
t.Cleanup(backend.Close)
ds := &models.DataSource{Url: backend.URL, Type: models.DS_GRAPHITE}
ds := &models.DataSource{Url: backend.URL, Type: models.DS_GRAPHITE, Name: "graphite"}
responseRecorder := &closeNotifierResponseRecorder{
ResponseRecorder: httptest.NewRecorder(),
+22 -7
View File
@@ -1,6 +1,7 @@
package models
import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
@@ -11,9 +12,9 @@ import (
"time"
"github.com/grafana/grafana-aws-sdk/pkg/sigv4"
"github.com/grafana/grafana/pkg/infra/metrics/metricutil"
"github.com/grafana/grafana/pkg/setting"
"github.com/mwitkow/go-conntrack"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
@@ -154,13 +155,15 @@ func (ds *DataSource) GetHttpTransport() (*dataSourceTransport, error) {
// Create transport which adds all
customHeaders := ds.getCustomHeaders()
datasourceLabelName, err := metricutil.SanitizeLabelName(ds.Name)
if err != nil {
return nil, err
}
transport := &http.Transport{
TLSClientConfig: tlsConfig,
Proxy: http.ProxyFromEnvironment,
Dial: (&net.Dialer{
Timeout: time.Duration(setting.DataProxyTimeout) * time.Second,
KeepAlive: time.Duration(setting.DataProxyKeepAlive) * time.Second,
}).Dial,
TLSClientConfig: tlsConfig,
Proxy: http.ProxyFromEnvironment,
DialContext: newConntrackDialContext(datasourceLabelName),
TLSHandshakeTimeout: time.Duration(setting.DataProxyTLSHandshakeTimeout) * time.Second,
ExpectContinueTimeout: time.Duration(setting.DataProxyExpectContinueTimeout) * time.Second,
MaxIdleConns: setting.DataProxyMaxIdleConns,
@@ -332,3 +335,15 @@ func awsServiceNamespace(dsType string) string {
panic(fmt.Sprintf("Unsupported datasource %q", dsType))
}
}
// newConntrackDialContext takes a http.DefaultTransport and adds the Conntrack Dialer
// so we can instrument outbound connections
func newConntrackDialContext(name string) func(context.Context, string, string) (net.Conn, error) {
return conntrack.NewDialContextFunc(
conntrack.DialWithName(name),
conntrack.DialWithDialer(&net.Dialer{
Timeout: time.Duration(setting.DataProxyTimeout) * time.Second,
KeepAlive: time.Duration(setting.DataProxyKeepAlive) * time.Second,
}),
)
}
+21 -1
View File
@@ -24,6 +24,7 @@ func TestDataSource_GetHttpTransport(t *testing.T) {
Id: 1,
Url: "http://k8s:8001",
Type: "Kubernetes",
Name: "kubernetes",
}
tr1, err := ds.GetHttpTransport()
@@ -54,6 +55,7 @@ func TestDataSource_GetHttpTransport(t *testing.T) {
Type: "Kubernetes",
SecureJsonData: map[string][]byte{"tlsCACert": tlsCaCert},
Updated: time.Now().Add(-2 * time.Minute),
Name: "kubernetes",
}
tr1, err := ds.GetHttpTransport()
@@ -91,6 +93,7 @@ func TestDataSource_GetHttpTransport(t *testing.T) {
Id: 1,
Url: "http://k8s:8001",
Type: "Kubernetes",
Name: "kubernetes",
JsonData: json,
SecureJsonData: map[string][]byte{
"tlsClientCert": tlsClientCert,
@@ -120,6 +123,7 @@ func TestDataSource_GetHttpTransport(t *testing.T) {
Id: 1,
Url: "http://k8s:8001",
Type: "Kubernetes",
Name: "kubernetes",
JsonData: json,
SecureJsonData: map[string][]byte{
"tlsCACert": tlsCaCert,
@@ -144,6 +148,7 @@ func TestDataSource_GetHttpTransport(t *testing.T) {
Id: 1,
Url: "http://k8s:8001",
Type: "Kubernetes",
Name: "kubernetes",
JsonData: json,
}
@@ -173,6 +178,7 @@ func TestDataSource_GetHttpTransport(t *testing.T) {
Id: 1,
Url: "http://k8s:8001",
Type: "Kubernetes",
Name: "kubernetes",
JsonData: json,
SecureJsonData: map[string][]byte{"httpHeaderValue1": encryptedData},
}
@@ -221,7 +227,9 @@ func TestDataSource_GetHttpTransport(t *testing.T) {
setting.SigV4AuthEnabled = true
t.Cleanup(func() { setting.SigV4AuthEnabled = origEnabled })
ds := DataSource{}
ds := DataSource{
Name: "empty",
}
tr, err := ds.GetHttpTransport()
require.NoError(t, err)
@@ -242,6 +250,7 @@ func TestDataSource_GetHttpTransport(t *testing.T) {
ds := DataSource{
JsonData: json,
Name: "empty",
}
tr, err := ds.GetHttpTransport()
@@ -250,6 +259,15 @@ func TestDataSource_GetHttpTransport(t *testing.T) {
_, ok := tr.next.(*http.Transport)
require.True(t, ok)
})
t.Run("Datasource name not set", func(t *testing.T) {
clearDSProxyCache(t)
ds := DataSource{}
_, err := ds.GetHttpTransport()
require.Error(t, err)
require.Equal(t, err.Error(), "label name cannot be empty")
})
}
func TestDataSource_DecryptedValue(t *testing.T) {
@@ -259,6 +277,7 @@ func TestDataSource_DecryptedValue(t *testing.T) {
ds := DataSource{
Id: 1,
Type: DS_INFLUXDB_08,
Name: "influx-db",
JsonData: simplejson.New(),
User: "user",
SecureJsonData: securejsondata.GetEncryptedJsonData(map[string]string{
@@ -286,6 +305,7 @@ func TestDataSource_DecryptedValue(t *testing.T) {
ds := DataSource{
Id: 1,
Type: DS_INFLUXDB_08,
Name: "influx-db",
JsonData: simplejson.New(),
User: "user",
SecureJsonData: securejsondata.GetEncryptedJsonData(map[string]string{
+3 -1
View File
@@ -10,7 +10,9 @@ import (
)
func TestTempo(t *testing.T) {
plug, err := NewExecutor(&models.DataSource{})
plug, err := NewExecutor(&models.DataSource{
Name: "tempo",
})
executor := plug.(*tempoExecutor)
require.NoError(t, err)