mirror of
https://github.com/fluxcd/flagger.git
synced 2026-04-15 06:57:34 +00:00
Merge pull request #557 from n0rad/master
Check prometheus is online with simple query
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user