Merge pull request #4342 from yixingjia/apimonitor

Add monitor API for Harbor components
This commit is contained in:
Daniel Jiang 2018-03-16 14:56:58 +08:00 committed by GitHub
commit cbedf099b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 85 additions and 9 deletions

2
.gitignore vendored
View File

@ -31,6 +31,8 @@ src/ui_ng/typings/
**/*yarn-error.log.* **/*yarn-error.log.*
.idea/ .idea/
.DS_Store .DS_Store
.project
.vscode/
**/node_modules **/node_modules
**/ssl/ **/ssl/
**/proxy.config.json **/proxy.config.json

View File

@ -0,0 +1,14 @@
package api
import (
"net/http"
"github.com/vmware/harbor/src/common/utils/log"
)
// Ping monitor the server status
func Ping(w http.ResponseWriter, r *http.Request) {
if err := writeJSON(w, "Pong"); err != nil {
log.Errorf("Failed to write response: %v", err)
return
}
}

View File

@ -0,0 +1,16 @@
package api
import(
"testing"
"net/http/httptest"
"net/http"
"github.com/stretchr/testify/assert"
"io/ioutil"
)
func TestPing(t *testing.T) {
w := httptest.NewRecorder()
Ping(w, nil)
assert.Equal(t, http.StatusOK, w.Code)
result, _:= ioutil.ReadAll(w.Body)
assert.Equal(t, "\"Pong\"", string(result))
}

View File

@ -31,7 +31,10 @@ func NewHandler() http.Handler {
"uiSecret": os.Getenv("UI_SECRET"), "uiSecret": os.Getenv("UI_SECRET"),
"jobserviceSecret": os.Getenv("JOBSERVICE_SECRET"), "jobserviceSecret": os.Getenv("JOBSERVICE_SECRET"),
} }
h = newAuthHandler(auth.NewSecretAuthenticator(secrets), h) insecureAPIs := map[string]bool{
"/api/ping":true,
}
h = newAuthHandler(auth.NewSecretAuthenticator(secrets), h, insecureAPIs)
h = gorilla_handlers.LoggingHandler(os.Stdout, h) h = gorilla_handlers.LoggingHandler(os.Stdout, h)
return h return h
} }
@ -39,12 +42,14 @@ func NewHandler() http.Handler {
type authHandler struct { type authHandler struct {
authenticator auth.Authenticator authenticator auth.Authenticator
handler http.Handler handler http.Handler
insecureAPIs map[string]bool
} }
func newAuthHandler(authenticator auth.Authenticator, handler http.Handler) http.Handler { func newAuthHandler(authenticator auth.Authenticator, handler http.Handler, insecureAPIs map[string]bool) http.Handler {
return &authHandler{ return &authHandler{
authenticator: authenticator, authenticator: authenticator,
handler: handler, handler: handler,
insecureAPIs: insecureAPIs,
} }
} }
@ -56,6 +61,12 @@ func (a *authHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return return
} }
if a.insecureAPIs !=nil && a.insecureAPIs[r.URL.Path] {
if a.handler != nil {
a.handler.ServeHTTP(w, r)
}
return
}
valid, err := a.authenticator.Authenticate(r) valid, err := a.authenticator.Authenticate(r)
if err != nil { if err != nil {
log.Errorf("failed to authenticate request: %v", err) log.Errorf("failed to authenticate request: %v", err)

View File

@ -45,28 +45,40 @@ func TestNewAuthHandler(t *testing.T) {
cases := []struct { cases := []struct {
authenticator auth.Authenticator authenticator auth.Authenticator
handler http.Handler handler http.Handler
insecureAPIs map[string]bool
responseCode int responseCode int
requestURL string
}{ }{
{nil, nil, http.StatusOK}, {nil, nil, nil, http.StatusOK,"http://localhost/good"},
{&fakeAuthenticator{ {&fakeAuthenticator{
authenticated: false, authenticated: false,
err: nil, err: nil,
}, nil, http.StatusUnauthorized}, }, nil, nil, http.StatusUnauthorized,"http://localhost/hello"},
{&fakeAuthenticator{ {&fakeAuthenticator{
authenticated: false, authenticated: false,
err: errors.New("error"), err: errors.New("error"),
}, nil, http.StatusInternalServerError}, }, nil, nil, http.StatusInternalServerError,"http://localhost/hello"},
{&fakeAuthenticator{ {&fakeAuthenticator{
authenticated: true, authenticated: true,
err: nil, err: nil,
}, &fakeHandler{http.StatusNotFound}, http.StatusNotFound}, }, &fakeHandler{http.StatusNotFound}, nil, http.StatusNotFound,"http://localhost/notexsit"},
{&fakeAuthenticator{
authenticated: false,
err: nil,
}, &fakeHandler{http.StatusOK},map[string]bool{"/api/ping":true,},http.StatusOK,"http://localhost/api/ping"},
} }
for _, c := range cases { for _, c := range cases {
handler := newAuthHandler(c.authenticator, c.handler) handler := newAuthHandler(c.authenticator, c.handler, c.insecureAPIs)
w := httptest.NewRecorder() w := httptest.NewRecorder()
handler.ServeHTTP(w, nil) r := httptest.NewRequest("GET",c.requestURL,nil)
handler.ServeHTTP(w, r)
assert.Equal(t, c.responseCode, w.Code, "unexpected response code") assert.Equal(t, c.responseCode, w.Code, "unexpected response code")
} }
handler := NewHandler()
w := httptest.NewRecorder()
r := httptest.NewRequest("GET","http://localhost/api/ping",nil)
handler.ServeHTTP(w,r)
} }

View File

@ -27,5 +27,6 @@ func newRouter() http.Handler {
r.HandleFunc("/api/configurations", api.UpdateCfgs).Methods("PUT") r.HandleFunc("/api/configurations", api.UpdateCfgs).Methods("PUT")
r.HandleFunc("/api/configurations/reset", api.ResetCfgs).Methods("POST") r.HandleFunc("/api/configurations/reset", api.ResetCfgs).Methods("POST")
r.HandleFunc("/api/systeminfo/capacity", api.Capacity).Methods("GET") r.HandleFunc("/api/systeminfo/capacity", api.Capacity).Methods("GET")
r.HandleFunc("/api/ping", api.Ping).Methods("GET")
return r return r
} }

View File

@ -138,7 +138,7 @@ func init() {
beego.Router("/api/replications", &ReplicationAPI{}) beego.Router("/api/replications", &ReplicationAPI{})
beego.Router("/api/labels", &LabelAPI{}, "post:Post;get:List") beego.Router("/api/labels", &LabelAPI{}, "post:Post;get:List")
beego.Router("/api/labels/:id([0-9]+", &LabelAPI{}, "get:Get;put:Put;delete:Delete") beego.Router("/api/labels/:id([0-9]+", &LabelAPI{}, "get:Get;put:Put;delete:Delete")
beego.Router("/api/ping", &SystemInfoAPI{}, "get:Ping")
_ = updateInitPassword(1, "Harbor12345") _ = updateInitPassword(1, "Harbor12345")
if err := core.Init(); err != nil { if err := core.Init(); err != nil {
@ -991,6 +991,11 @@ func (a testapi) GetGeneralInfo() (int, []byte, error) {
return request(_sling, jsonAcceptHeader) return request(_sling, jsonAcceptHeader)
} }
func (a testapi) Ping() (int, []byte, error) {
_sling := sling.New().Get(a.basePath).Path("/api/ping")
return request(_sling, jsonAcceptHeader)
}
//Get system cert //Get system cert
func (a testapi) CertGet(authInfo usrInfo) (int, []byte, error) { func (a testapi) CertGet(authInfo usrInfo) (int, []byte, error) {
_sling := sling.New().Get(a.basePath) _sling := sling.New().Get(a.basePath)

View File

@ -247,3 +247,9 @@ func getClairVulnStatus() *models.ClairVulnerabilityStatus {
res.Details = details res.Details = details
return res return res
} }
// Ping ping the harbor UI service.
func (sia *SystemInfoAPI) Ping() {
sia.Data["json"] = "Pong"
sia.ServeJSON()
}

View File

@ -91,3 +91,10 @@ func TestGetCert(t *testing.T) {
} }
CommonDelUser() CommonDelUser()
} }
func TestPing(t *testing.T) {
apiTest := newHarborAPI()
code, _, err := apiTest.Ping()
assert := assert.New(t)
assert.Nil(err, fmt.Sprintf("Unexpected Error: %v", err))
assert.Equal(200, code, fmt.Sprintf("Unexpected status code: %d", code))
}

View File

@ -60,6 +60,7 @@ func initRouters() {
} }
// API // API
beego.Router("/api/ping", &api.SystemInfoAPI{}, "get:Ping")
beego.Router("/api/search", &api.SearchAPI{}) beego.Router("/api/search", &api.SearchAPI{})
beego.Router("/api/projects/", &api.ProjectAPI{}, "get:List;post:Post") beego.Router("/api/projects/", &api.ProjectAPI{}, "get:List;post:Post")
beego.Router("/api/projects/:id([0-9]+)/logs", &api.ProjectAPI{}, "get:Logs") beego.Router("/api/projects/:id([0-9]+)/logs", &api.ProjectAPI{}, "get:Logs")
@ -114,6 +115,7 @@ func initRouters() {
beego.Router("/service/token", &token.Handler{}) beego.Router("/service/token", &token.Handler{})
beego.Router("/registryproxy/*", &controllers.RegistryProxy{}, "*:Handle") beego.Router("/registryproxy/*", &controllers.RegistryProxy{}, "*:Handle")
//Error pages //Error pages
beego.ErrorController(&controllers.ErrorController{}) beego.ErrorController(&controllers.ErrorController{})