Skip to content

Commit

Permalink
[FAB-15814] Add endpoint for versioning metadata
Browse files Browse the repository at this point in the history
Adds a /version endpoint to the operations
server that serves the Version and CommitSHA
from the common/metadata package

Change-Id: Ic16e044f989bf9bdf827637412217fb07a8394e3
Signed-off-by: Brett Logan <Brett.T.Logan@ibm.com>
(cherry picked from commit b66fc33)
  • Loading branch information
Brett Logan committed Nov 14, 2019
1 parent e369169 commit 95ffcdc
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 0 deletions.
10 changes: 10 additions & 0 deletions core/operations/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/hyperledger/fabric-lib-go/healthz"
"github.com/hyperledger/fabric/common/flogging"
"github.com/hyperledger/fabric/common/flogging/httpadmin"
"github.com/hyperledger/fabric/common/metadata"
"github.com/hyperledger/fabric/common/metrics"
"github.com/hyperledger/fabric/common/metrics/disabled"
"github.com/hyperledger/fabric/common/metrics/prometheus"
Expand Down Expand Up @@ -86,6 +87,7 @@ func NewSystem(o Options) *System {
system.initializeHealthCheckHandler()
system.initializeLoggingHandler()
system.initializeMetricsProvider()
system.initializeVersionInfoHandler()

return system
}
Expand Down Expand Up @@ -201,6 +203,14 @@ func (s *System) initializeHealthCheckHandler() {
s.mux.Handle("/healthz", s.handlerChain(s.healthHandler, false))
}

func (s *System) initializeVersionInfoHandler() {
versionInfo := &VersionInfoHandler{
CommitSHA: metadata.CommitSHA,
Version: metadata.Version,
}
s.mux.Handle("/version", s.handlerChain(versionInfo, false))
}

func (s *System) startMetricsTickers() error {
m := s.options.Metrics
if s.statsd != nil {
Expand Down
11 changes: 11 additions & 0 deletions core/operations/system_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,17 @@ var _ = Describe("System", func() {
}
})

It("hosts an unsecured endpoint for the version information", func() {
err := system.Start()
Expect(err).NotTo(HaveOccurred())

versionURL := fmt.Sprintf("https://%s/version", system.Addr())
resp, err := client.Get(versionURL)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusOK))
resp.Body.Close()
})

It("hosts a secure endpoint for logging", func() {
err := system.Start()
Expect(err).NotTo(HaveOccurred())
Expand Down
50 changes: 50 additions & 0 deletions core/operations/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
Copyright IBM Corp All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package operations

import (
"encoding/json"
"fmt"
"net/http"

"github.com/hyperledger/fabric/common/flogging"
)

type VersionInfoHandler struct {
CommitSHA string `json:"CommitSHA,omitempty"`
Version string `json:"Version,omitempty"`
}

func (m *VersionInfoHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
switch req.Method {
case http.MethodGet:
m.sendResponse(resp, http.StatusOK, m)
default:
err := fmt.Errorf("invalid request method: %s", req.Method)
m.sendResponse(resp, http.StatusBadRequest, err)
}
}

type errorResponse struct {
Error string `json:"Error"`
}

func (m *VersionInfoHandler) sendResponse(resp http.ResponseWriter, code int, payload interface{}) {
if err, ok := payload.(error); ok {
payload = &errorResponse{Error: err.Error()}
}
js, err := json.Marshal(payload)
if err != nil {
logger := flogging.MustGetLogger("operations.runner")
logger.Errorw("failed to encode payload", "error", err)
resp.WriteHeader(http.StatusInternalServerError)
} else {
resp.WriteHeader(code)
resp.Header().Set("Content-Type", "application/json")
resp.Write(js)
}
}
43 changes: 43 additions & 0 deletions core/operations/version_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
Copyright IBM Corp All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package operations

import (
"net/http"
"net/http/httptest"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

var _ = Describe("Version", func() {
It("returns 200 if the method is GET", func() {
resp := httptest.NewRecorder()

versionInfoHandler := &VersionInfoHandler{Version: "latest"}
versionInfoHandler.ServeHTTP(resp, &http.Request{Method: http.MethodGet})
Expect(resp.Result().StatusCode).To(Equal(http.StatusOK))
Expect(resp.Body).To(MatchJSON(`{"Version": "latest"}`))
})

It("returns 400 when an unsupported method is used", func() {
resp := httptest.NewRecorder()

versionInfoHandler := &VersionInfoHandler{}
versionInfoHandler.ServeHTTP(resp, &http.Request{Method: http.MethodPut})
Expect(resp.Result().StatusCode).To(Equal(http.StatusBadRequest))
Expect(resp.Body).To(MatchJSON(`{"Error": "invalid request method: PUT"}`))
})

It("returns 500 when the payload is invalid JSON", func() {
resp := httptest.NewRecorder()

versionInfoHandler := &VersionInfoHandler{}
versionInfoHandler.sendResponse(resp, 200, make(chan int))
Expect(resp.Result().StatusCode).To(Equal(http.StatusInternalServerError))
})
})

0 comments on commit 95ffcdc

Please sign in to comment.