Merge pull request #557 from n0rad/master

Check prometheus is online with simple query
This commit is contained in:
Takeshi Yoneda
2020-04-15 22:27:42 +09:00
committed by GitHub
2 changed files with 60 additions and 45 deletions
+7 -31
View File
@@ -15,6 +15,8 @@ import (
flaggerv1 "github.com/weaveworks/flagger/pkg/apis/flagger/v1beta1"
)
const prometheusOnlineQuery = "vector(1)"
// PrometheusProvider executes promQL queries
type PrometheusProvider struct {
timeout time.Duration
@@ -132,41 +134,15 @@ func (p *PrometheusProvider) RunQuery(query string) (float64, error) {
return *value, nil
}
// IsOnline calls the Prometheus status endpoint and returns an error if the API is unreachable
// IsOnline run simple Prometheus query and returns an error if the API is unreachable
func (p *PrometheusProvider) IsOnline() (bool, error) {
u, err := url.Parse("./api/v1/status/flags")
value, err := p.RunQuery(prometheusOnlineQuery)
if err != nil {
return false, fmt.Errorf("url.Parse failed: %w", err)
}
u.Path = path.Join(p.url.Path, u.Path)
u = p.url.ResolveReference(u)
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
return false, fmt.Errorf("http.NewRequest failed: %w", err)
return false, fmt.Errorf("running query failed: %w", err)
}
if p.username != "" && p.password != "" {
req.SetBasicAuth(p.username, p.password)
}
ctx, cancel := context.WithTimeout(req.Context(), p.timeout)
defer cancel()
r, err := http.DefaultClient.Do(req.WithContext(ctx))
if err != nil {
return false, fmt.Errorf("request failed: %w", err)
}
defer r.Body.Close()
b, err := ioutil.ReadAll(r.Body)
if err != nil {
return false, fmt.Errorf("error reading body: %w", err)
}
if 400 <= r.StatusCode {
return false, fmt.Errorf("error response: %s", string(b))
if value != float64(1) {
return false, fmt.Errorf("value is not 1 for query: %s", prometheusOnlineQuery)
}
return true, nil
+53 -14
View File
@@ -147,22 +147,61 @@ func TestPrometheusProvider_RunQueryWithBasicAuth(t *testing.T) {
}
func TestPrometheusProvider_IsOnline(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusBadGateway)
}))
defer ts.Close()
t.Run("fail", func(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusBadGateway)
}))
defer ts.Close()
clients := prometheusFake()
clients := prometheusFake()
template, err := clients.flaggerClient.FlaggerV1beta1().MetricTemplates("default").Get(context.TODO(), "prometheus", metav1.GetOptions{})
require.NoError(t, err)
template.Spec.Provider.Address = ts.URL
template.Spec.Provider.SecretRef = nil
template, err := clients.flaggerClient.FlaggerV1beta1().MetricTemplates("default").Get(context.TODO(), "prometheus", metav1.GetOptions{})
require.NoError(t, err)
template.Spec.Provider.Address = ts.URL
template.Spec.Provider.SecretRef = nil
prom, err := NewPrometheusProvider(template.Spec.Provider, nil)
require.NoError(t, err)
prom, err := NewPrometheusProvider(template.Spec.Provider, nil)
require.NoError(t, err)
ok, err := prom.IsOnline()
assert.Error(t, err, "Got no error wanted %v", http.StatusBadGateway)
assert.False(t, ok)
ok, err := prom.IsOnline()
assert.Error(t, err, "Got no error wanted %v", http.StatusBadGateway)
assert.False(t, ok)
})
t.Run("ok", func(t *testing.T) {
expected := `vector(1)`
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
promql := r.URL.Query()["query"][0]
assert.Equal(t, expected, promql)
if assert.Contains(t, r.Header, "Authorization") {
}
header, ok := r.Header["Authorization"]
if assert.True(t, ok, "Authorization header not found") {
assert.True(t, strings.Contains(header[0], "Basic"), "Basic authorization header not found")
}
json := `{"status":"success","data":{"resultType":"vector","result":[{"metric":{},"value":[1545905245.458,"1"]}]}}`
w.Write([]byte(json))
}))
defer ts.Close()
clients := prometheusFake()
template, err := clients.flaggerClient.FlaggerV1beta1().MetricTemplates("default").Get(context.TODO(), "prometheus", metav1.GetOptions{})
require.NoError(t, err)
template.Spec.Provider.Address = ts.URL
secret, err := clients.kubeClient.CoreV1().Secrets("default").Get(context.TODO(), "prometheus", metav1.GetOptions{})
require.NoError(t, err)
prom, err := NewPrometheusProvider(template.Spec.Provider, secret.Data)
require.NoError(t, err)
ok, err := prom.IsOnline()
require.NoError(t, err)
assert.Equal(t, true, ok)
})
}