mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Add transport cache for reverse proxy (#6776)
* Add transport cache for reverse proxy * Use updated at in cache
This commit is contained in:
parent
d3e47e50c1
commit
bc69c8ef40
@ -7,6 +7,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httputil"
|
"net/http/httputil"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/api/cloudwatch"
|
"github.com/grafana/grafana/pkg/api/cloudwatch"
|
||||||
@ -18,7 +19,29 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/util"
|
"github.com/grafana/grafana/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type proxyTransportCache struct {
|
||||||
|
cache map[int64]cachedTransport
|
||||||
|
sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
type cachedTransport struct {
|
||||||
|
updated time.Time
|
||||||
|
|
||||||
|
*http.Transport
|
||||||
|
}
|
||||||
|
|
||||||
|
var ptc = proxyTransportCache{
|
||||||
|
cache: make(map[int64]cachedTransport),
|
||||||
|
}
|
||||||
|
|
||||||
func DataProxyTransport(ds *m.DataSource) (*http.Transport, error) {
|
func DataProxyTransport(ds *m.DataSource) (*http.Transport, error) {
|
||||||
|
ptc.Lock()
|
||||||
|
defer ptc.Unlock()
|
||||||
|
|
||||||
|
if t, present := ptc.cache[ds.Id]; present && ds.Updated.Equal(t.updated) {
|
||||||
|
return t.Transport, nil
|
||||||
|
}
|
||||||
|
|
||||||
transport := &http.Transport{
|
transport := &http.Transport{
|
||||||
TLSClientConfig: &tls.Config{
|
TLSClientConfig: &tls.Config{
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
@ -56,6 +79,12 @@ func DataProxyTransport(ds *m.DataSource) (*http.Transport, error) {
|
|||||||
}
|
}
|
||||||
transport.TLSClientConfig.Certificates = []tls.Certificate{cert}
|
transport.TLSClientConfig.Certificates = []tls.Certificate{cert}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ptc.cache[ds.Id] = cachedTransport{
|
||||||
|
Transport: transport,
|
||||||
|
updated: ds.Updated,
|
||||||
|
}
|
||||||
|
|
||||||
return transport, nil
|
return transport, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
|
||||||
@ -16,6 +17,7 @@ import (
|
|||||||
func TestDataSourceProxy(t *testing.T) {
|
func TestDataSourceProxy(t *testing.T) {
|
||||||
|
|
||||||
Convey("When getting graphite datasource proxy", t, func() {
|
Convey("When getting graphite datasource proxy", t, func() {
|
||||||
|
clearCache()
|
||||||
ds := m.DataSource{Url: "htttp://graphite:8080", Type: m.DS_GRAPHITE}
|
ds := m.DataSource{Url: "htttp://graphite:8080", Type: m.DS_GRAPHITE}
|
||||||
targetUrl, err := url.Parse(ds.Url)
|
targetUrl, err := url.Parse(ds.Url)
|
||||||
proxy := NewReverseProxy(&ds, "/render", targetUrl)
|
proxy := NewReverseProxy(&ds, "/render", targetUrl)
|
||||||
@ -38,6 +40,7 @@ func TestDataSourceProxy(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
Convey("When getting influxdb datasource proxy", t, func() {
|
Convey("When getting influxdb datasource proxy", t, func() {
|
||||||
|
clearCache()
|
||||||
ds := m.DataSource{
|
ds := m.DataSource{
|
||||||
Type: m.DS_INFLUXDB_08,
|
Type: m.DS_INFLUXDB_08,
|
||||||
Url: "http://influxdb:8083",
|
Url: "http://influxdb:8083",
|
||||||
@ -65,38 +68,85 @@ func TestDataSourceProxy(t *testing.T) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Convey("When caching a datasource proxy", t, func() {
|
||||||
|
clearCache()
|
||||||
|
ds := m.DataSource{
|
||||||
|
Id: 1,
|
||||||
|
Url: "http://k8s:8001",
|
||||||
|
Type: "Kubernetes",
|
||||||
|
}
|
||||||
|
|
||||||
|
t1, err := DataProxyTransport(&ds)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
t2, err := DataProxyTransport(&ds)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
Convey("Should be using the cached proxy", func() {
|
||||||
|
So(t2, ShouldEqual, t1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
Convey("When getting kubernetes datasource proxy", t, func() {
|
Convey("When getting kubernetes datasource proxy", t, func() {
|
||||||
|
clearCache()
|
||||||
setting.SecretKey = "password"
|
setting.SecretKey = "password"
|
||||||
|
|
||||||
json := simplejson.New()
|
json := simplejson.New()
|
||||||
json.Set("tlsAuth", true)
|
json.Set("tlsAuth", true)
|
||||||
json.Set("tlsAuthWithCACert", true)
|
json.Set("tlsAuthWithCACert", true)
|
||||||
|
|
||||||
|
t := time.Now()
|
||||||
ds := m.DataSource{
|
ds := m.DataSource{
|
||||||
Url: "htttp://k8s:8001",
|
Url: "http://k8s:8001",
|
||||||
Type: "Kubernetes",
|
Type: "Kubernetes",
|
||||||
JsonData: json,
|
Updated: t.Add(-2 * time.Minute),
|
||||||
SecureJsonData: map[string][]byte{
|
|
||||||
"tlsCACert": util.Encrypt([]byte(caCert), "password"),
|
|
||||||
"tlsClientCert": util.Encrypt([]byte(clientCert), "password"),
|
|
||||||
"tlsClientKey": util.Encrypt([]byte(clientKey), "password"),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
targetUrl, err := url.Parse(ds.Url)
|
|
||||||
proxy := NewReverseProxy(&ds, "", targetUrl)
|
transport, err := DataProxyTransport(&ds)
|
||||||
proxy.Transport, err = DataProxyTransport(&ds)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
transport, ok := proxy.Transport.(*http.Transport)
|
Convey("Should have no cert", func() {
|
||||||
|
So(transport.TLSClientConfig.InsecureSkipVerify, ShouldEqual, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
ds.JsonData = json
|
||||||
|
ds.SecureJsonData = map[string][]byte{
|
||||||
|
"tlsCACert": util.Encrypt([]byte(caCert), "password"),
|
||||||
|
"tlsClientCert": util.Encrypt([]byte(clientCert), "password"),
|
||||||
|
"tlsClientKey": util.Encrypt([]byte(clientKey), "password"),
|
||||||
|
}
|
||||||
|
ds.Updated = t.Add(-1 * time.Minute)
|
||||||
|
|
||||||
|
transport, err = DataProxyTransport(&ds)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
Convey("Should add cert", func() {
|
Convey("Should add cert", func() {
|
||||||
So(ok, ShouldBeTrue)
|
|
||||||
So(transport.TLSClientConfig.InsecureSkipVerify, ShouldEqual, false)
|
So(transport.TLSClientConfig.InsecureSkipVerify, ShouldEqual, false)
|
||||||
So(len(transport.TLSClientConfig.Certificates), ShouldEqual, 1)
|
So(len(transport.TLSClientConfig.Certificates), ShouldEqual, 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ds.JsonData = nil
|
||||||
|
ds.SecureJsonData = map[string][]byte{}
|
||||||
|
ds.Updated = t
|
||||||
|
|
||||||
|
transport, err = DataProxyTransport(&ds)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
Convey("Should remove cert", func() {
|
||||||
|
So(transport.TLSClientConfig.InsecureSkipVerify, ShouldEqual, true)
|
||||||
|
So(len(transport.TLSClientConfig.Certificates), ShouldEqual, 0)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func clearCache() {
|
||||||
|
ptc.Lock()
|
||||||
|
defer ptc.Unlock()
|
||||||
|
|
||||||
|
ptc.cache = make(map[int64]cachedTransport)
|
||||||
|
}
|
||||||
|
|
||||||
const caCert string = `-----BEGIN CERTIFICATE-----
|
const caCert string = `-----BEGIN CERTIFICATE-----
|
||||||
MIIDATCCAemgAwIBAgIJAMQ5hC3CPDTeMA0GCSqGSIb3DQEBCwUAMBcxFTATBgNV
|
MIIDATCCAemgAwIBAgIJAMQ5hC3CPDTeMA0GCSqGSIb3DQEBCwUAMBcxFTATBgNV
|
||||||
BAMMDGNhLWs4cy1zdGhsbTAeFw0xNjEwMjcwODQyMjdaFw00NDAzMTQwODQyMjda
|
BAMMDGNhLWs4cy1zdGhsbTAeFw0xNjEwMjcwODQyMjdaFw00NDAzMTQwODQyMjda
|
||||||
|
Loading…
Reference in New Issue
Block a user