Files
grafana/pkg/tests/apis/zanzana_reconcile.go

87 lines
2.4 KiB
Go

package apis
import (
"bytes"
"context"
"net/http"
"testing"
"time"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/common/expfmt"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/services/featuremgmt"
)
const zanzanaReconcileLastSuccessMetric = "grafana_zanzana_reconcile_last_success_timestamp_seconds"
// AwaitZanzanaReconcileNext waits for a Zanzana reconciliation cycle whose last-success timestamp
// has been incremented from its current value. This ensures a reconciliation has occurred after
// this function is called.
//
// It is a no-op unless the `zanzana` feature toggle is enabled for the running test env.
func AwaitZanzanaReconcileNext(t *testing.T, helper *K8sTestHelper) {
t.Helper()
enabled := false
if helper != nil {
enabled = helper.GetEnv().FeatureToggles.GetEnabled(context.Background())[featuremgmt.FlagZanzana]
}
if helper == nil || !enabled {
return
}
baselineTimestamp, _ := getZanzanaReconcileLastSuccessTimestampSeconds(t, helper)
require.EventuallyWithT(t, func(c *assert.CollectT) {
ts, ok := getZanzanaReconcileLastSuccessTimestampSeconds(t, helper)
assert.True(c, ok, "expected to find %s in /metrics", zanzanaReconcileLastSuccessMetric)
if !ok {
return
}
assert.Greater(c, ts, baselineTimestamp, "expected %s (%v) > baseline (%v)", zanzanaReconcileLastSuccessMetric, ts, baselineTimestamp)
}, 30*time.Second, 50*time.Millisecond)
}
func getZanzanaReconcileLastSuccessTimestampSeconds(t *testing.T, helper *K8sTestHelper) (float64, bool) {
t.Helper()
rsp := DoRequest(helper, RequestParams{
User: helper.Org1.Admin,
Path: "/metrics",
Accept: "text/plain",
}, &struct{}{})
if rsp.Response == nil || rsp.Response.StatusCode != http.StatusOK {
return 0, false
}
parser := expfmt.NewTextParser(model.UTF8Validation)
metrics, err := parser.TextToMetricFamilies(bytes.NewReader(rsp.Body))
if err != nil {
return 0, false
}
metric := metrics[zanzanaReconcileLastSuccessMetric]
if metric == nil || len(metric.Metric) == 0 {
return 0, false
}
m := metric.Metric[0]
switch metric.GetType() {
case dto.MetricType_GAUGE:
if m.Gauge == nil {
return 0, false
}
return m.Gauge.GetValue(), true
case dto.MetricType_UNTYPED:
if m.Untyped == nil {
return 0, false
}
return m.Untyped.GetValue(), true
default:
return 0, false
}
}