From ed2c05a77e8bdf822b13b59f5a8aabbd1e3347b9 Mon Sep 17 00:00:00 2001 From: repenno Date: Mon, 8 Oct 2018 08:25:17 -0700 Subject: [PATCH] Expose version information via REST API /v1/data/system/version will return information similar to: Version: 0.9.3-dev Build Commit: c5171ed5-dirty Build Timestamp: 2018-10-07T02:12:58Z Build Hostname: JOHNDOE-M-9130 Signed-off-by: repenno Signed-off-by: Torin Sandall --- server/server.go | 44 +++++++++++++++++++++++++++++++++++++++++-- server/server_test.go | 20 ++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/server/server.go b/server/server.go index 008e43475c..8c483b2efc 100644 --- a/server/server.go +++ b/server/server.go @@ -7,6 +7,7 @@ package server import ( "bytes" "context" + "crypto/tls" "encoding/json" "fmt" "html/template" @@ -21,8 +22,6 @@ import ( "sync" "time" - "crypto/tls" - "net/url" "github.com/gorilla/mux" @@ -132,6 +131,7 @@ func New() *Server { router.Handle("/metrics", promhttp.HandlerFor(promRegistry, promhttp.HandlerOpts{})).Methods(http.MethodGet) s.registerHandler(router, 0, "/data/{path:.+}", http.MethodPost, promhttp.InstrumentHandlerDuration(v0DataDur, http.HandlerFunc(s.v0DataPost))) s.registerHandler(router, 0, "/data", http.MethodPost, promhttp.InstrumentHandlerDuration(v0DataDur, http.HandlerFunc(s.v0DataPost))) + s.registerHandler(router, 1, "/data/system/version", http.MethodGet, promhttp.InstrumentHandlerDuration(v1DataDur, http.HandlerFunc(s.v1VersionGet))) s.registerHandler(router, 1, "/data/system/diagnostics", http.MethodGet, promhttp.InstrumentHandlerDuration(v1DataDur, http.HandlerFunc(s.v1DiagnosticsGet))) s.registerHandler(router, 1, "/data/{path:.+}", http.MethodDelete, promhttp.InstrumentHandlerDuration(v1DataDur, http.HandlerFunc(s.v1DataDelete))) s.registerHandler(router, 1, "/data/{path:.+}", http.MethodPut, promhttp.InstrumentHandlerDuration(v1DataDur, http.HandlerFunc(s.v1DataPut))) @@ -605,6 +605,46 @@ func (s *Server) v1DiagnosticsGet(w http.ResponseWriter, r *http.Request) { writer.JSON(w, 200, resp, pretty) } +func (s *Server) v1VersionGet(w http.ResponseWriter, r *http.Request) { + + code := 200 + + opaVersion := ` +{ + "result": { + "Version": "{{.Version}}", + "BuildCommit": "{{.BuildCommit}}", + "BuildTimestamp": "{{.BuildTimestamp}}", + "BuildHostname": "{{.BuildHostname}}" + } +} + ` + tmpl, err := template.New("").Parse(opaVersion) + if err != nil { + panic(err) + } + + var buf bytes.Buffer + + err = tmpl.Execute(&buf, struct { + Version string + BuildCommit string + BuildTimestamp string + BuildHostname string + }{ + Version: version.Version, + BuildCommit: version.Vcs, + BuildTimestamp: version.Timestamp, + BuildHostname: version.Hostname, + }) + + jsonBytes := buf.Bytes() + + headers := w.Header() + headers.Add("Content-Type", "application/json") + writer.Bytes(w, code, jsonBytes) +} + func (s *Server) v1CompilePost(w http.ResponseWriter, r *http.Request) { ctx := r.Context() pretty := getBoolParam(r.URL, types.ParamPrettyV1, true) diff --git a/server/server_test.go b/server/server_test.go index 46738a1741..6282f0a9d3 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -15,6 +15,7 @@ import ( "net/http/httptest" "net/http/httputil" "reflect" + "regexp" "strings" "testing" "time" @@ -1207,6 +1208,25 @@ func TestIndexGetCompileError(t *testing.T) { } } +func TestVersionGet(t *testing.T) { + + f := newFixture(t) + + get := newReqV1(http.MethodGet, "/data/system/version", "") + f.server.Handler.ServeHTTP(f.recorder, get) + if f.recorder.Code != 200 { + t.Fatalf("Expected 200 OK but got %v", f.recorder) + return + } + + page := f.recorder.Body.String() + var re = regexp.MustCompile(`[\s\S]*Version\b[\s\S]*BuildCommit\b[\s\S]*BuildTimestamp\b[\s\S]*BuildHostname\b`) + if !re.MatchString(page) { + t.Errorf("Expected page to contain 'version' but got: %v", page) + return + } +} + func TestPoliciesPutV1(t *testing.T) { f := newFixture(t) req := newReqV1(http.MethodPut, "/policies/1", testMod)