Commit 9ed21c6a by stuart nelson Committed by Carl Bergquist

Add transport cache for reverse proxy (#6776)

* Add transport cache for reverse proxy
* Use updated at in cache
parent 158656f5
......@@ -7,6 +7,7 @@ import (
"net/http"
"net/http/httputil"
"net/url"
"sync"
"time"
"github.com/grafana/grafana/pkg/api/cloudwatch"
......@@ -18,7 +19,29 @@ import (
"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) {
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{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
......@@ -56,6 +79,12 @@ func DataProxyTransport(ds *m.DataSource) (*http.Transport, error) {
}
transport.TLSClientConfig.Certificates = []tls.Certificate{cert}
}
ptc.cache[ds.Id] = cachedTransport{
Transport: transport,
updated: ds.Updated,
}
return transport, nil
}
......
......@@ -4,6 +4,7 @@ import (
"net/http"
"net/url"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
......@@ -16,6 +17,7 @@ import (
func TestDataSourceProxy(t *testing.T) {
Convey("When getting graphite datasource proxy", t, func() {
clearCache()
ds := m.DataSource{Url: "htttp://graphite:8080", Type: m.DS_GRAPHITE}
targetUrl, err := url.Parse(ds.Url)
proxy := NewReverseProxy(&ds, "/render", targetUrl)
......@@ -38,6 +40,7 @@ func TestDataSourceProxy(t *testing.T) {
})
Convey("When getting influxdb datasource proxy", t, func() {
clearCache()
ds := m.DataSource{
Type: m.DS_INFLUXDB_08,
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() {
clearCache()
setting.SecretKey = "password"
json := simplejson.New()
json.Set("tlsAuth", true)
json.Set("tlsAuthWithCACert", true)
t := time.Now()
ds := m.DataSource{
Url: "htttp://k8s:8001",
Type: "Kubernetes",
JsonData: json,
SecureJsonData: map[string][]byte{
"tlsCACert": util.Encrypt([]byte(caCert), "password"),
"tlsClientCert": util.Encrypt([]byte(clientCert), "password"),
"tlsClientKey": util.Encrypt([]byte(clientKey), "password"),
},
Url: "http://k8s:8001",
Type: "Kubernetes",
Updated: t.Add(-2 * time.Minute),
}
targetUrl, err := url.Parse(ds.Url)
proxy := NewReverseProxy(&ds, "", targetUrl)
proxy.Transport, err = DataProxyTransport(&ds)
transport, err := DataProxyTransport(&ds)
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() {
So(ok, ShouldBeTrue)
So(transport.TLSClientConfig.InsecureSkipVerify, ShouldEqual, false)
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-----
MIIDATCCAemgAwIBAgIJAMQ5hC3CPDTeMA0GCSqGSIb3DQEBCwUAMBcxFTATBgNV
BAMMDGNhLWs4cy1zdGhsbTAeFw0xNjEwMjcwODQyMjdaFw00NDAzMTQwODQyMjda
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment