Merge pull request #1975 from ywk253100/170408_target

Modify ping targat and put target api
This commit is contained in:
Wenkai Yin 2017-04-10 14:45:57 +08:00 committed by GitHub
commit ad02cab82a
5 changed files with 190 additions and 76 deletions

View File

@ -1230,12 +1230,12 @@ paths:
description: | description: |
This endpoint is for ping validates whether the target is reachable and whether the credential is valid. This endpoint is for ping validates whether the target is reachable and whether the credential is valid.
parameters: parameters:
- name: id - name: target
in: query in: body
type: integer description: The target object.
format: int64 required: true
required: false schema:
description: The replication's policy ID. $ref: '#/definitions/PingTarget'
tags: tags:
- Products - Products
responses: responses:
@ -1249,6 +1249,31 @@ paths:
description: Target not found. description: Target not found.
500: 500:
description: Unexpected internal errors. description: Unexpected internal errors.
/targets/{id}/ping:
post:
summary: Ping target.
description: |
This endpoint is for ping target.
parameters:
- name: id
in: path
type: integer
format: int64
required: true
description: The replication's target ID.
tags:
- Products
responses:
200:
description: Ping replication's target successfully.
400:
description: Can not ping target.
401:
description: User need to log in first.
404:
description: Target ID does not exist.
500:
description: Unexpected internal errors.
/targets/{id}: /targets/{id}:
put: put:
summary: Update replication's target. summary: Update replication's target.
@ -1265,7 +1290,7 @@ paths:
in: body in: body
required: true required: true
schema: schema:
$ref: '#/definitions/RepTargetPost' $ref: '#/definitions/PutTarget'
description: Updates of replication's target. description: Updates of replication's target.
tags: tags:
- Products - Products
@ -1999,6 +2024,33 @@ definitions:
password: password:
type: string type: string
description: The target server password. description: The target server password.
PingTarget:
type: object
properties:
endpoint:
type: string
description: The target address URL string.
username:
type: string
description: The target server username.
password:
type: string
description: The target server password.
PutTarget:
type: object
properties:
name:
type: string
description: The target name.
endpoint:
type: string
description: The target address URL string.
username:
type: string
description: The target server username.
password:
type: string
description: The target server password.
HasAdminRole: HasAdminRole:
type: object type: object
properties: properties:

View File

@ -96,6 +96,7 @@ func init() {
beego.Router("/api/targets/:id([0-9]+)", &TargetAPI{}) beego.Router("/api/targets/:id([0-9]+)", &TargetAPI{})
beego.Router("/api/targets/:id([0-9]+)/policies/", &TargetAPI{}, "get:ListPolicies") beego.Router("/api/targets/:id([0-9]+)/policies/", &TargetAPI{}, "get:ListPolicies")
beego.Router("/api/targets/ping", &TargetAPI{}, "post:Ping") beego.Router("/api/targets/ping", &TargetAPI{}, "post:Ping")
beego.Router("/api/targets/:id([0-9]+)/ping", &TargetAPI{}, "post:PingByID")
beego.Router("/api/policies/replication/:id([0-9]+)", &RepPolicyAPI{}) beego.Router("/api/policies/replication/:id([0-9]+)", &RepPolicyAPI{})
beego.Router("/api/policies/replication", &RepPolicyAPI{}, "get:List") beego.Router("/api/policies/replication", &RepPolicyAPI{}, "get:List")
beego.Router("/api/policies/replication", &RepPolicyAPI{}, "post:Post;delete:Delete") beego.Router("/api/policies/replication", &RepPolicyAPI{}, "post:Post;delete:Delete")
@ -628,11 +629,24 @@ func (a testapi) ListTargets(authInfo usrInfo, targetName string) (int, []apilib
return httpStatusCode, successPayload, err return httpStatusCode, successPayload, err
} }
//Ping target by targetID //Ping target
func (a testapi) PingTargetsByID(authInfo usrInfo, targetID string) (int, error) { func (a testapi) PingTarget(authInfo usrInfo, body interface{}) (int, error) {
_sling := sling.New().Post(a.basePath) _sling := sling.New().Post(a.basePath)
path := "/api/targets/ping?id=" + targetID path := "/api/targets/ping"
_sling = _sling.Path(path)
_sling = _sling.BodyJSON(body)
httpStatusCode, _, err := request(_sling, jsonAcceptHeader, authInfo)
return httpStatusCode, err
}
//PingTargetByID ...
func (a testapi) PingTargetByID(authInfo usrInfo, id int) (int, error) {
_sling := sling.New().Post(a.basePath)
path := fmt.Sprintf("/api/targets/%d/ping", id)
_sling = _sling.Path(path) _sling = _sling.Path(path)

View File

@ -60,48 +60,7 @@ func (t *TargetAPI) Prepare() {
} }
} }
// Ping validates whether the target is reachable and whether the credential is valid func (t *TargetAPI) ping(endpoint, username, password string) {
func (t *TargetAPI) Ping() {
var endpoint, username, password string
idStr := t.GetString("id")
if len(idStr) != 0 {
id, err := strconv.ParseInt(idStr, 10, 64)
if err != nil {
t.CustomAbort(http.StatusBadRequest, fmt.Sprintf("id %s is invalid", idStr))
}
target, err := dao.GetRepTarget(id)
if err != nil {
log.Errorf("failed to get target %d: %v", id, err)
t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}
if target == nil {
t.CustomAbort(http.StatusNotFound, http.StatusText(http.StatusNotFound))
}
endpoint = target.URL
username = target.Username
password = target.Password
if len(password) != 0 {
password, err = utils.ReversibleDecrypt(password, t.secretKey)
if err != nil {
log.Errorf("failed to decrypt password: %v", err)
t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}
}
} else {
endpoint = t.GetString("endpoint")
if len(endpoint) == 0 {
t.CustomAbort(http.StatusBadRequest, "id or endpoint is needed")
}
username = t.GetString("username")
password = t.GetString("password")
}
verify, err := config.VerifyRemoteCert() verify, err := config.VerifyRemoteCert()
if err != nil { if err != nil {
log.Errorf("failed to check whether insecure or not: %v", err) log.Errorf("failed to check whether insecure or not: %v", err)
@ -133,6 +92,48 @@ func (t *TargetAPI) Ping() {
} }
} }
// PingByID ping target by ID
func (t *TargetAPI) PingByID() {
id := t.GetIDFromURL()
target, err := dao.GetRepTarget(id)
if err != nil {
log.Errorf("failed to get target %d: %v", id, err)
t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}
if target == nil {
t.CustomAbort(http.StatusNotFound, fmt.Sprintf("target %d not found", id))
}
endpoint := target.URL
username := target.Username
password := target.Password
if len(password) != 0 {
password, err = utils.ReversibleDecrypt(password, t.secretKey)
if err != nil {
log.Errorf("failed to decrypt password: %v", err)
t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}
}
t.ping(endpoint, username, password)
}
// Ping validates whether the target is reachable and whether the credential is valid
func (t *TargetAPI) Ping() {
req := struct {
Endpoint string `json:"endpoint"`
Username string `json:"username"`
Password string `json:"password"`
}{}
t.DecodeJSONReq(&req)
if len(req.Endpoint) == 0 {
t.CustomAbort(http.StatusBadRequest, "endpoint is required")
}
t.ping(req.Endpoint, req.Username, req.Password)
}
// Get ... // Get ...
func (t *TargetAPI) Get() { func (t *TargetAPI) Get() {
id := t.GetIDFromURL() id := t.GetIDFromURL()
@ -217,13 +218,13 @@ func (t *TargetAPI) Post() {
func (t *TargetAPI) Put() { func (t *TargetAPI) Put() {
id := t.GetIDFromURL() id := t.GetIDFromURL()
originalTarget, err := dao.GetRepTarget(id) target, err := dao.GetRepTarget(id)
if err != nil { if err != nil {
log.Errorf("failed to get target %d: %v", id, err) log.Errorf("failed to get target %d: %v", id, err)
t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
} }
if originalTarget == nil { if target == nil {
t.CustomAbort(http.StatusNotFound, http.StatusText(http.StatusNotFound)) t.CustomAbort(http.StatusNotFound, http.StatusText(http.StatusNotFound))
} }
@ -245,10 +246,33 @@ func (t *TargetAPI) Put() {
t.CustomAbort(http.StatusBadRequest, "the target is associated with policy which is enabled") t.CustomAbort(http.StatusBadRequest, "the target is associated with policy which is enabled")
} }
target := &models.RepTarget{} req := struct {
t.DecodeJSONReqAndValidate(target) Name *string `json:"name"`
Endpoint *string `json:"endpoint"`
Username *string `json:"username"`
Password *string `json:"password"`
}{}
t.DecodeJSONReq(&req)
if target.Name != originalTarget.Name { originalName := target.Name
originalURL := target.URL
if req.Name != nil {
target.Name = *req.Name
}
if req.Endpoint != nil {
target.URL = *req.Endpoint
}
if req.Username != nil {
target.Username = *req.Username
}
if req.Password != nil {
target.Password = *req.Password
}
t.Validate(target)
if target.Name != originalName {
ta, err := dao.GetRepTargetByName(target.Name) ta, err := dao.GetRepTargetByName(target.Name)
if err != nil { if err != nil {
log.Errorf("failed to get target %s: %v", target.Name, err) log.Errorf("failed to get target %s: %v", target.Name, err)
@ -260,7 +284,7 @@ func (t *TargetAPI) Put() {
} }
} }
if target.URL != originalTarget.URL { if target.URL != originalURL {
ta, err := dao.GetRepTargetByEndpoint(target.URL) ta, err := dao.GetRepTargetByEndpoint(target.URL)
if err != nil { if err != nil {
log.Errorf("failed to get target [ %s ]: %v", target.URL, err) log.Errorf("failed to get target [ %s ]: %v", target.URL, err)
@ -272,8 +296,6 @@ func (t *TargetAPI) Put() {
} }
} }
target.ID = id
if len(target.Password) != 0 { if len(target.Password) != 0 {
target.Password, err = utils.ReversibleEncrypt(target.Password, t.secretKey) target.Password, err = utils.ReversibleEncrypt(target.Password, t.secretKey)
if err != nil { if err != nil {

View File

@ -103,12 +103,48 @@ func TestTargetPing(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
apiTest := newHarborAPI() apiTest := newHarborAPI()
fmt.Println("Testing Targets Ping Post API")
//case 1
body := struct {
Endpoint string `json:"endpoint"`
Username string `json:"username"`
Password string `json:"password"`
}{
Endpoint: os.Getenv("REGISTRY_URL"),
Username: adminName,
Password: adminPwd,
}
httpStatusCode, err = apiTest.PingTarget(*admin, body)
if err != nil {
t.Error("Error while ping target", err.Error())
t.Log(err)
} else {
assert.Equal(int(200), httpStatusCode, "")
}
//case 2
body.Endpoint = ""
httpStatusCode, err = apiTest.PingTarget(*admin, body)
if err != nil {
t.Error("Error while ping target", err.Error())
} else {
assert.Equal(int(400), httpStatusCode, "")
}
}
func TestTargetPingByID(t *testing.T) {
var httpStatusCode int
var err error
assert := assert.New(t)
apiTest := newHarborAPI()
fmt.Println("Testing Targets Ping Post API") fmt.Println("Testing Targets Ping Post API")
//-------------------case 1 : response code = 200------------------------// //-------------------case 1 : response code = 200------------------------//
fmt.Println("case 1 : response code = 200") fmt.Println("case 1 : response code = 200")
id := strconv.Itoa(addTargetID) id := addTargetID
httpStatusCode, err = apiTest.PingTargetsByID(*admin, id) httpStatusCode, err = apiTest.PingTargetByID(*admin, id)
if err != nil { if err != nil {
t.Error("Error whihle ping target", err.Error()) t.Error("Error whihle ping target", err.Error())
t.Log(err) t.Log(err)
@ -118,26 +154,15 @@ func TestTargetPing(t *testing.T) {
//--------------case 2 : response code = 404,target not found------------// //--------------case 2 : response code = 404,target not found------------//
fmt.Println("case 2 : response code = 404,target not found") fmt.Println("case 2 : response code = 404,target not found")
id = "1111"
httpStatusCode, err = apiTest.PingTargetsByID(*admin, id) id = 1111
httpStatusCode, err = apiTest.PingTargetByID(*admin, id)
if err != nil { if err != nil {
t.Error("Error whihle ping target", err.Error()) t.Error("Error whihle ping target", err.Error())
t.Log(err) t.Log(err)
} else { } else {
assert.Equal(int(404), httpStatusCode, "httpStatusCode should be 404") assert.Equal(int(404), httpStatusCode, "httpStatusCode should be 404")
} }
//------------case 3 : response code = 400,targetID is invalid-----------//
fmt.Println("case 2 : response code = 400,target not found")
id = "cc"
httpStatusCode, err = apiTest.PingTargetsByID(*admin, id)
if err != nil {
t.Error("Error whihle ping target", err.Error())
t.Log(err)
} else {
assert.Equal(int(400), httpStatusCode, "httpStatusCode should be 400")
}
} }
func TestTargetGetByID(t *testing.T) { func TestTargetGetByID(t *testing.T) {

View File

@ -89,6 +89,7 @@ func initRouters() {
beego.Router("/api/targets/:id([0-9]+)", &api.TargetAPI{}) beego.Router("/api/targets/:id([0-9]+)", &api.TargetAPI{})
beego.Router("/api/targets/:id([0-9]+)/policies/", &api.TargetAPI{}, "get:ListPolicies") beego.Router("/api/targets/:id([0-9]+)/policies/", &api.TargetAPI{}, "get:ListPolicies")
beego.Router("/api/targets/ping", &api.TargetAPI{}, "post:Ping") beego.Router("/api/targets/ping", &api.TargetAPI{}, "post:Ping")
beego.Router("/api/targets/:id([0-9]+)/ping", &api.TargetAPI{}, "post:PingByID")
beego.Router("/api/users/:id/sysadmin", &api.UserAPI{}, "put:ToggleUserAdminRole") beego.Router("/api/users/:id/sysadmin", &api.UserAPI{}, "put:ToggleUserAdminRole")
beego.Router("/api/repositories/top", &api.RepositoryAPI{}, "get:GetTopRepos") beego.Router("/api/repositories/top", &api.RepositoryAPI{}, "get:GetTopRepos")
beego.Router("/api/logs", &api.LogAPI{}) beego.Router("/api/logs", &api.LogAPI{})