Skip to content

Commit 0a1c112

Browse files
authored
Support Prometheus /api/v1/status/buildinfo API on Querier/QFE (#4978)
* support Prometheus /api/v1/status/buildinfo API Signed-off-by: Ben Ye <[email protected]> * add unit test Signed-off-by: Ben Ye <[email protected]> * update api doc Signed-off-by: Ben Ye <[email protected]> * revert docs update Signed-off-by: Ben Ye <[email protected]> Signed-off-by: Ben Ye <[email protected]>
1 parent b1cd7b2 commit 0a1c112

File tree

4 files changed

+75
-2
lines changed

4 files changed

+75
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Changelog
22

33
## master / unreleased
4+
* [FEATURE] Querier/Query Frontend: support Prometheus /api/v1/status/buildinfo API. #4978
45

56
## 1.14.0 in progress
67

pkg/api/api.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ type Distributor interface {
352352
UserStatsHandler(w http.ResponseWriter, r *http.Request)
353353
}
354354

355-
// RegisterQueryable registers the the default routes associated with the querier
355+
// RegisterQueryable registers the default routes associated with the querier
356356
// module.
357357
func (a *API) RegisterQueryable(
358358
queryable storage.SampleAndChunkQueryable,
@@ -374,6 +374,7 @@ func (a *API) RegisterQueryAPI(handler http.Handler) {
374374
a.RegisterRoute(path.Join(a.cfg.PrometheusHTTPPrefix, "/api/v1/label/{name}/values"), handler, true, "GET")
375375
a.RegisterRoute(path.Join(a.cfg.PrometheusHTTPPrefix, "/api/v1/series"), handler, true, "GET", "POST", "DELETE")
376376
a.RegisterRoute(path.Join(a.cfg.PrometheusHTTPPrefix, "/api/v1/metadata"), handler, true, "GET")
377+
a.RegisterRoute(path.Join(a.cfg.PrometheusHTTPPrefix, "/api/v1/status/buildinfo"), handler, true, "GET")
377378

378379
// Register Legacy Routers
379380
a.RegisterRoute(path.Join(a.cfg.LegacyHTTPPrefix, "/api/v1/read"), handler, true, "POST")
@@ -384,6 +385,7 @@ func (a *API) RegisterQueryAPI(handler http.Handler) {
384385
a.RegisterRoute(path.Join(a.cfg.LegacyHTTPPrefix, "/api/v1/label/{name}/values"), handler, true, "GET")
385386
a.RegisterRoute(path.Join(a.cfg.LegacyHTTPPrefix, "/api/v1/series"), handler, true, "GET", "POST", "DELETE")
386387
a.RegisterRoute(path.Join(a.cfg.LegacyHTTPPrefix, "/api/v1/metadata"), handler, true, "GET")
388+
a.RegisterRoute(path.Join(a.cfg.LegacyHTTPPrefix, "/api/v1/status/buildinfo"), handler, true, "GET")
387389
}
388390

389391
// RegisterQueryFrontend registers the Prometheus routes supported by the

pkg/api/handlers.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/prometheus/client_golang/prometheus/promauto"
1616
dto "github.com/prometheus/client_model/go"
1717
"github.com/prometheus/common/route"
18+
"github.com/prometheus/common/version"
1819
"github.com/prometheus/prometheus/config"
1920
"github.com/prometheus/prometheus/storage"
2021
v1 "github.com/prometheus/prometheus/web/api/v1"
@@ -211,7 +212,14 @@ func NewQuerierHandler(
211212
false,
212213
regexp.MustCompile(".*"),
213214
func() (v1.RuntimeInfo, error) { return v1.RuntimeInfo{}, errors.New("not implemented") },
214-
&v1.PrometheusVersion{},
215+
&v1.PrometheusVersion{
216+
Version: version.Version,
217+
Branch: version.Branch,
218+
Revision: version.Revision,
219+
BuildUser: version.BuildUser,
220+
BuildDate: version.BuildDate,
221+
GoVersion: version.GoVersion,
222+
},
215223
// This is used for the stats API which we should not support. Or find other ways to.
216224
prometheus.GathererFunc(func() ([]*dto.MetricFamily, error) { return nil, nil }),
217225
reg,
@@ -255,6 +263,7 @@ func NewQuerierHandler(
255263
router.Path(path.Join(prefix, "/api/v1/label/{name}/values")).Methods("GET").Handler(promRouter)
256264
router.Path(path.Join(prefix, "/api/v1/series")).Methods("GET", "POST", "DELETE").Handler(promRouter)
257265
router.Path(path.Join(prefix, "/api/v1/metadata")).Methods("GET").Handler(promRouter)
266+
router.Path(path.Join(prefix, "/api/v1/status/buildinfo")).Methods("GET").Handler(promRouter)
258267

259268
// TODO(gotjosh): This custom handler is temporary until we're able to vendor the changes in:
260269
// https://github.com/prometheus/prometheus/pull/7125/files
@@ -268,6 +277,7 @@ func NewQuerierHandler(
268277
router.Path(path.Join(legacyPrefix, "/api/v1/label/{name}/values")).Methods("GET").Handler(legacyPromRouter)
269278
router.Path(path.Join(legacyPrefix, "/api/v1/series")).Methods("GET", "POST", "DELETE").Handler(legacyPromRouter)
270279
router.Path(path.Join(legacyPrefix, "/api/v1/metadata")).Methods("GET").Handler(legacyPromRouter)
280+
router.Path(path.Join(legacyPrefix, "/api/v1/status/buildinfo")).Methods("GET").Handler(legacyPromRouter)
271281

272282
// Track execution time.
273283
return stats.NewWallTimeMiddleware().Wrap(router)

pkg/api/handlers_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
package api
22

33
import (
4+
"encoding/json"
45
"io"
56
"net/http"
67
"net/http/httptest"
8+
"runtime"
79
"strings"
810
"testing"
911

12+
"github.com/prometheus/common/version"
13+
v1 "github.com/prometheus/prometheus/web/api/v1"
1014
"github.com/stretchr/testify/assert"
1115
"github.com/stretchr/testify/require"
16+
"github.com/weaveworks/common/user"
17+
18+
"github.com/cortexproject/cortex/pkg/purger"
1219
)
1320

1421
func TestIndexHandlerPrefix(t *testing.T) {
@@ -189,3 +196,56 @@ func TestConfigOverrideHandler(t *testing.T) {
189196
assert.NoError(t, err)
190197
assert.Equal(t, []byte("config"), body)
191198
}
199+
200+
func TestBuildInfoAPI(t *testing.T) {
201+
type buildInfo struct {
202+
Status string `json:"status"`
203+
Data v1.PrometheusVersion `json:"data"`
204+
}
205+
206+
for _, tc := range []struct {
207+
name string
208+
version string
209+
branch string
210+
revision string
211+
expected buildInfo
212+
}{
213+
{
214+
name: "empty",
215+
expected: buildInfo{Status: "success", Data: v1.PrometheusVersion{
216+
GoVersion: runtime.Version(),
217+
}},
218+
},
219+
{
220+
name: "set versions",
221+
version: "v0.14.0",
222+
branch: "test",
223+
revision: "foo",
224+
expected: buildInfo{Status: "success", Data: v1.PrometheusVersion{
225+
Version: "v0.14.0",
226+
Branch: "test",
227+
Revision: "foo",
228+
GoVersion: runtime.Version(),
229+
}},
230+
},
231+
} {
232+
t.Run(tc.name, func(t *testing.T) {
233+
cfg := Config{}
234+
version.Version = tc.version
235+
version.Branch = tc.branch
236+
version.Revision = tc.revision
237+
handler := NewQuerierHandler(cfg, nil, nil, nil, nil, purger.NewNoopTombstonesLoader(), nil, &FakeLogger{})
238+
writer := httptest.NewRecorder()
239+
req := httptest.NewRequest("GET", "/api/v1/status/buildinfo", nil)
240+
req = req.WithContext(user.InjectOrgID(req.Context(), "test"))
241+
handler.ServeHTTP(writer, req)
242+
out, err := io.ReadAll(writer.Body)
243+
require.NoError(t, err)
244+
245+
var info buildInfo
246+
err = json.Unmarshal(out, &info)
247+
require.NoError(t, err)
248+
require.Equal(t, tc.expected, info)
249+
})
250+
}
251+
}

0 commit comments

Comments
 (0)