Datasource: Fix storing timeout option as numeric (#35441)

#31871 introduced support for configuring timeout in seconds
for HTTP data sources. That had a bug where backend expected
a numeric timeout value where it was actually stored as a
string. This should resolve this by requiring input to be
numbers, storing input as numeric and falling back to string
value if there's no numeric value.

Ref #31871
This commit is contained in:
Marcus Efraimsson
2021-06-10 10:27:14 +02:00
committed by GitHub
parent eff2410bae
commit d15d87db8a
3 changed files with 33 additions and 2 deletions

View File

@ -167,13 +167,14 @@ export const DataSourceHttpSettings: React.FC<HttpSettingsProps> = (props) => {
<div className="gf-form">
<FormField
label="Timeout"
type="number"
labelWidth={13}
inputWidth={20}
tooltip="HTTP request timeout in seconds"
value={dataSourceConfig.jsonData.timeout}
onChange={(event) => {
onSettingsChange({
jsonData: { ...dataSourceConfig.jsonData, timeout: event.currentTarget.value },
jsonData: { ...dataSourceConfig.jsonData, timeout: parseInt(event.currentTarget.value, 10) },
});
}}
/>

View File

@ -4,6 +4,7 @@ import (
"crypto/tls"
"fmt"
"net/http"
"strconv"
"sync"
"time"
@ -17,8 +18,15 @@ func (ds *DataSource) getTimeout() time.Duration {
timeout := 0
if ds.JsonData != nil {
timeout = ds.JsonData.Get("timeout").MustInt()
if timeout <= 0 {
if timeoutStr := ds.JsonData.Get("timeout").MustString(); timeoutStr != "" {
if t, err := strconv.Atoi(timeoutStr); err == nil {
timeout = t
}
if timeout == 0 {
}
}
}
if timeout <= 0 {
timeout = setting.DataProxyTimeout
}
return time.Duration(timeout) * time.Second

View File

@ -14,6 +14,7 @@ import (
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -310,6 +311,27 @@ func TestDataSource_GetHttpTransport(t *testing.T) {
})
}
func TestDataSource_getTimeout(t *testing.T) {
setting.DataProxyTimeout = 30
testCases := []struct {
jsonData *simplejson.Json
expectedTimeout time.Duration
}{
{jsonData: simplejson.New(), expectedTimeout: 30 * time.Second},
{jsonData: simplejson.NewFromAny(map[string]interface{}{"timeout": nil}), expectedTimeout: 30 * time.Second},
{jsonData: simplejson.NewFromAny(map[string]interface{}{"timeout": 0}), expectedTimeout: 30 * time.Second},
{jsonData: simplejson.NewFromAny(map[string]interface{}{"timeout": 1}), expectedTimeout: time.Second},
{jsonData: simplejson.NewFromAny(map[string]interface{}{"timeout": "2"}), expectedTimeout: 2 * time.Second},
}
for _, tc := range testCases {
ds := &DataSource{
JsonData: tc.jsonData,
}
assert.Equal(t, tc.expectedTimeout, ds.getTimeout())
}
}
func TestDataSource_DecryptedValue(t *testing.T) {
t.Run("When datasource hasn't been updated, encrypted JSON should be fetched from cache", func(t *testing.T) {
ClearDSDecryptionCache()