refactor api.

This commit is contained in:
Wenkai Yin 2017-03-21 17:54:02 +08:00
parent a05f1e3507
commit b461ba54a8
5 changed files with 145 additions and 172 deletions

View File

@ -438,6 +438,64 @@ paths:
description: Project ID does not exist.
500:
description: Unexpected internal errors.
/projects/{project_id}/repositories:
get:
summary: Get repositories accompany with relevant project and repo name.
description: |
This endpoint let user search repositories accompanying with relevant project ID and repo name.
parameters:
- name: project_id
in: path
type: integer
format: int32
required: true
description: Relevant project ID.
- name: detail
in: query
type: boolean
required: false
description: Get detail info or not.
- name: q
in: query
type: string
required: false
description: Repo name for filtering results.
- name: page
in: query
type: integer
format: int32
required: false
description: The page nubmer, default is 1.
- name: page_size
in: query
type: integer
format: int32
required: false
description: The size of per page, default is 10, maximum is 100.
tags:
- Products
responses:
200:
description: If detail is false, the response body is a string array which contains the names of repositories, or the response body contains an object array as described in schema.
schema:
type: array
items:
$ref: '#/definitions/Repository'
headers:
X-Total-Count:
description: The total count of repositories
type: integer
Link:
description: Link refers to the previous page and next page
type: string
400:
description: Invalid project ID.
403:
description: Project is not public or current user is irrelevant to the repository.
404:
description: Project ID does not exist.
500:
description: Unexpected internal errors.
/statistics:
get:
summary: Get projects number and repositories number relevant to the user
@ -644,84 +702,27 @@ paths:
description: User ID does not exist.
500:
description: Unexpected internal errors.
/repositories:
get:
summary: Get repositories accompany with relevant project and repo name.
description: |
This endpoint let user search repositories accompanying with relevant project ID and repo name.
parameters:
- name: project_id
in: query
type: integer
format: int32
required: true
description: Relevant project ID.
- name: detail
in: query
type: boolean
required: false
description: Get detail info or not.
- name: q
in: query
type: string
required: false
description: Repo name for filtering results.
- name: page
in: query
type: integer
format: int32
required: false
description: The page nubmer, default is 1.
- name: page_size
in: query
type: integer
format: int32
required: false
description: The size of per page, default is 10, maximum is 100.
tags:
- Products
responses:
200:
description: If detail is false, the response body is a string array which contains the names of repositories, or the response body contains an object array as described in schema.
schema:
type: array
items:
$ref: '#/definitions/Repository'
headers:
X-Total-Count:
description: The total count of repositories
type: integer
Link:
description: Link refers to the previous page and next page
type: string
400:
description: Invalid project ID.
403:
description: Project is not public or current user is irrelevant to the repository.
404:
description: Project ID does not exist.
500:
description: Unexpected internal errors.
/repositories/{repo_name}/tags/{tag}:
delete:
summary: Delete a repository or a tag in a repository.
summary: Delete a tag in a repository.
description: |
This endpoint let user delete repositories and tags with repo name and tag.
This endpoint let user delete tags with repo name and tag.
parameters:
- name: repo_name
in: query
in: path
type: string
required: true
description: The name of repository which will be deleted.
- name: tag
in: query
in: path
type: string
required: false
required: true
description: Tag of a repository.
tags:
- Products
responses:
200:
description: Delete repository or tag successfully.
description: Delete tag successfully.
400:
description: Invalid repo_name.
401:
@ -730,14 +731,14 @@ paths:
description: Repository or tag not found.
403:
description: Forbidden.
/repositories/tags:
/repositories/{repo_name}/tags:
get:
summary: Get tags of a relevant repository.
description: |
This endpoint aims to retrieve tags from a relevant repository.
parameters:
- name: repo_name
in: query
in: path
type: string
required: true
description: Relevant repository name.
@ -757,19 +758,42 @@ paths:
$ref: '#/definitions/DetailedTag'
500:
description: Unexpected internal errors.
/repositories/manifests:
delete:
summary: Delete all tags of a repository.
description: |
This endpoint let user delete all tags with repo name.
parameters:
- name: repo_name
in: path
type: string
required: true
description: The name of repository which will be deleted.
tags:
- Products
responses:
200:
description: Delete successfully.
400:
description: Invalid repo_name.
401:
description: Unauthorized.
404:
description: Repository not found.
403:
description: Forbidden.
/repositories/{repo_name}/tags/{tag}/manifest:
get:
summary: Get manifests of a relevant repository.
description: |
This endpoint aims to retreive manifests from a relevant repository.
parameters:
- name: repo_name
in: query
in: path
type: string
required: true
description: Repository name
- name: tag
in: query
in: path
type: string
required: true
description: Tag name
@ -789,7 +813,7 @@ paths:
description: Retrieved manifests from a relevant repository not found.
500:
description: Unexpected internal errors.
/repositories/signatures:
/repositories/{repo_name}/signatures:
get:
summary: Get signature information of a repository
description: |
@ -799,7 +823,7 @@ paths:
return an empty list with response code 200, instead of 404
parameters:
- name: repo_name
in: query
in: path
type: string
required: true
description: repository name.

View File

@ -82,12 +82,14 @@ func init() {
beego.Router("/api/projects/:id/publicity", &ProjectAPI{}, "put:ToggleProjectPublic")
beego.Router("/api/projects/:id([0-9]+)/logs/filter", &ProjectAPI{}, "post:FilterAccessLog")
beego.Router("/api/projects/:pid([0-9]+)/members/?:mid", &ProjectMemberAPI{}, "get:Get;post:Post;delete:Delete;put:Put")
beego.Router("/api/projects/:id([0-9]+)/repositories", &RepositoryAPI{}, "get:Get")
beego.Router("/api/statistics", &StatisticAPI{})
beego.Router("/api/users/?:id", &UserAPI{})
beego.Router("/api/logs", &LogAPI{})
beego.Router("/api/repositories", &RepositoryAPI{})
beego.Router("/api/repositories/tags", &RepositoryAPI{}, "get:GetTags")
beego.Router("/api/repositories/manifests", &RepositoryAPI{}, "get:GetManifests")
beego.Router("/api/repositories/*/tags/?:tag", &RepositoryAPI{}, "delete:Delete")
beego.Router("/api/repositories/*/tags", &RepositoryAPI{}, "get:GetTags")
beego.Router("/api/repositories/*/tags/:tag/manifest", &RepositoryAPI{}, "get:GetManifests")
beego.Router("/api/repositories/*/signatures", &RepositoryAPI{}, "get:GetSignatures")
beego.Router("/api/repositories/top", &RepositoryAPI{}, "get:GetTopRepos")
beego.Router("/api/targets/", &TargetAPI{}, "get:List")
beego.Router("/api/targets/", &TargetAPI{}, "post:Post")
@ -461,20 +463,18 @@ func (a testapi) GetRepos(authInfo usrInfo, projectID,
keyword, detail string) (int, interface{}, error) {
_sling := sling.New().Get(a.basePath)
path := "/api/repositories/"
path := fmt.Sprintf("/api/projects/%s/repositories", projectID)
_sling = _sling.Path(path)
type QueryParams struct {
ProjectID string `url:"project_id"`
Detail string `url:"detail"`
Keyword string `url:"q"`
Detail string `url:"detail"`
Keyword string `url:"q"`
}
_sling = _sling.QueryStruct(&QueryParams{
ProjectID: projectID,
Detail: detail,
Keyword: keyword,
Detail: detail,
Keyword: keyword,
})
code, body, err := request(_sling, jsonAcceptHeader, authInfo)
if err != nil {
@ -505,18 +505,16 @@ func (a testapi) GetReposTags(authInfo usrInfo, repoName,
detail string) (int, interface{}, error) {
_sling := sling.New().Get(a.basePath)
path := "/api/repositories/tags"
path := fmt.Sprintf("/api/repositories/%s/tags", repoName)
_sling = _sling.Path(path)
type QueryParams struct {
RepoName string `url:"repo_name"`
Detail string `url:"detail"`
Detail string `url:"detail"`
}
_sling = _sling.QueryStruct(&QueryParams{
RepoName: repoName,
Detail: detail,
Detail: detail,
})
httpStatusCode, body, err := request(_sling, jsonAcceptHeader, authInfo)
if err != nil {
@ -546,16 +544,10 @@ func (a testapi) GetReposTags(authInfo usrInfo, repoName,
func (a testapi) GetReposManifests(authInfo usrInfo, repoName string, tag string) (int, error) {
_sling := sling.New().Get(a.basePath)
path := "/api/repositories/manifests"
path := fmt.Sprintf("/api/repositories/%s/tags/%s/manifest", repoName, tag)
_sling = _sling.Path(path)
type QueryParams struct {
RepoName string `url:"repo_name"`
Tag string `url:"tag"`
}
_sling = _sling.QueryStruct(&QueryParams{RepoName: repoName, Tag: tag})
httpStatusCode, _, err := request(_sling, jsonAcceptHeader, authInfo)
return httpStatusCode, err
}

View File

@ -70,8 +70,8 @@ type manifestResp struct {
// Get ...
func (ra *RepositoryAPI) Get() {
projectID, err := ra.GetInt64("project_id")
if err != nil || projectID <= 0 {
projectID, err := ra.GetInt64(":id")
if err != nil {
ra.CustomAbort(http.StatusBadRequest, "invalid project_id")
}
@ -169,10 +169,8 @@ func populateTagsCount(repositories []*models.RepoRecord) ([]*repoResp, error) {
// Delete ...
func (ra *RepositoryAPI) Delete() {
repoName := ra.GetString("repo_name")
if len(repoName) == 0 {
ra.CustomAbort(http.StatusBadRequest, "repo_name is nil")
}
// using :splat to get * part in path
repoName := ra.GetString(":splat")
projectName, _ := utils.ParseRepository(repoName)
project, err := dao.GetProjectByName(projectName)
@ -197,7 +195,7 @@ func (ra *RepositoryAPI) Delete() {
}
tags := []string{}
tag := ra.GetString("tag")
tag := ra.GetString(":tag")
if len(tag) == 0 {
tagList, err := rc.ListTag()
if err != nil {
@ -284,12 +282,9 @@ type tag struct {
Tags []string `json:"tags"`
}
// GetTags handles GET /api/repositories/tags
// GetTags returns tags of a repository
func (ra *RepositoryAPI) GetTags() {
repoName := ra.GetString("repo_name")
if len(repoName) == 0 {
ra.CustomAbort(http.StatusBadRequest, "repo_name is nil")
}
repoName := ra.GetString(":splat")
detail := ra.GetString("detail") == "1" || ra.GetString("detail") == "true"
projectName, _ := utils.ParseRepository(repoName)
@ -380,14 +375,10 @@ func listTag(client *registry.Repository) ([]string, error) {
return tags, nil
}
// GetManifests handles GET /api/repositories/manifests
// GetManifests returns the manifest of a tag
func (ra *RepositoryAPI) GetManifests() {
repoName := ra.GetString("repo_name")
tag := ra.GetString("tag")
if len(repoName) == 0 || len(tag) == 0 {
ra.CustomAbort(http.StatusBadRequest, "repo_name or tag is nil")
}
repoName := ra.GetString(":splat")
tag := ra.GetString(":tag")
version := ra.GetString("version")
if len(version) == 0 {
@ -535,7 +526,7 @@ func (ra *RepositoryAPI) getUsername() (string, error) {
return "", nil
}
//GetTopRepos handles request GET /api/repositories/top
//GetTopRepos returns the most populor repositories
func (ra *RepositoryAPI) GetTopRepos() {
count, err := ra.GetInt("count", 10)
if err != nil || count <= 0 {
@ -579,7 +570,7 @@ func (ra *RepositoryAPI) GetTopRepos() {
ra.ServeJSON()
}
//GetSignatures handles request GET /api/repositories/signatures
//GetSignatures returns signatures of a repository
func (ra *RepositoryAPI) GetSignatures() {
//use this func to init session.
ra.GetUserIDForRequest()
@ -587,10 +578,8 @@ func (ra *RepositoryAPI) GetSignatures() {
if err != nil {
log.Warningf("Error when getting username: %v", err)
}
repoName := ra.GetString("repo_name")
if len(repoName) == 0 {
ra.CustomAbort(http.StatusBadRequest, "repo_name is nil")
}
repoName := ra.GetString(":splat")
targets, err := getNotaryTargets(username, repoName)
if err != nil {
log.Errorf("Error while fetching signature from notary: %v", err)

View File

@ -32,20 +32,10 @@ func TestGetRepos(t *testing.T) {
}
}
//-------------------case 2 : response code = 400------------------------//
fmt.Println("case 2 : response code = 400,invalid project_id")
projectID = "ccc"
httpStatusCode, _, err := apiTest.GetRepos(*admin, projectID, keyword, detail)
if err != nil {
t.Error("Error whihle get repos by projectID", err.Error())
t.Log(err)
} else {
assert.Equal(int(400), httpStatusCode, "httpStatusCode should be 400")
}
//-------------------case 3 : response code = 404------------------------//
fmt.Println("case 3 : response code = 404:project not found")
//-------------------case 2 : response code = 404------------------------//
fmt.Println("case 2 : response code = 404:project not found")
projectID = "111"
httpStatusCode, _, err = apiTest.GetRepos(*admin, projectID, keyword, detail)
httpStatusCode, _, err := apiTest.GetRepos(*admin, projectID, keyword, detail)
if err != nil {
t.Error("Error whihle get repos by projectID", err.Error())
t.Log(err)
@ -53,8 +43,8 @@ func TestGetRepos(t *testing.T) {
assert.Equal(int(404), httpStatusCode, "httpStatusCode should be 404")
}
//-------------------case 4 : response code = 200------------------------//
fmt.Println("case 4 : response code = 200")
//-------------------case 3 : response code = 200------------------------//
fmt.Println("case 3 : response code = 200")
projectID = "1"
detail = "false"
code, repositories, err = apiTest.GetRepos(*admin, projectID, keyword, detail)
@ -78,31 +68,18 @@ func TestGetReposTags(t *testing.T) {
assert := assert.New(t)
apiTest := newHarborAPI()
repository := ""
//-------------------case 1 : response code = 404------------------------//
fmt.Println("case 1 : response code = 404,repo not found")
repository := "errorRepos"
detail := "false"
fmt.Println("Testing ReposTags Get API")
//-------------------case 1 : response code = 400------------------------//
fmt.Println("case 1 : response code = 400,repo_name is nil")
code, _, err := apiTest.GetReposTags(*admin, repository, detail)
if err != nil {
t.Errorf("failed to get tags of repository %s: %v", repository, err)
} else {
assert.Equal(int(400), code, "httpStatusCode should be 400")
}
//-------------------case 2 : response code = 404------------------------//
fmt.Println("case 2 : response code = 404,repo not found")
repository = "errorRepos"
code, _, err = apiTest.GetReposTags(*admin, repository, detail)
if err != nil {
t.Errorf("failed to get tags of repository %s: %v", repository, err)
} else {
assert.Equal(int(404), code, "httpStatusCode should be 404")
}
//-------------------case 3 : response code = 200------------------------//
fmt.Println("case 3 : response code = 200")
//-------------------case 2 : response code = 200------------------------//
fmt.Println("case 2 : response code = 200")
repository = "library/hello-world"
code, tags, err := apiTest.GetReposTags(*admin, repository, detail)
if err != nil {
@ -117,8 +94,8 @@ func TestGetReposTags(t *testing.T) {
}
}
//-------------------case 4 : response code = 200------------------------//
fmt.Println("case 4 : response code = 200")
//-------------------case 3 : response code = 200------------------------//
fmt.Println("case 3 : response code = 200")
repository = "library/hello-world"
detail = "true"
code, tags, err = apiTest.GetReposTags(*admin, repository, detail)
@ -169,18 +146,8 @@ func TestGetReposManifests(t *testing.T) {
assert.Equal(int(404), httpStatusCode, "httpStatusCode should be 404")
}
//-------------------case 3 : response code = 400------------------------//
fmt.Println("case 3 : response code = 400,repo_name or is nil")
repoName = ""
httpStatusCode, err = apiTest.GetReposManifests(*admin, repoName, tag)
if err != nil {
t.Error("Error whihle get reposManifests by repoName and tag", err.Error())
t.Log(err)
} else {
assert.Equal(int(400), httpStatusCode, "httpStatusCode should be 400")
}
//-------------------case 4 : response code = 404------------------------//
fmt.Println("case 4 : response code = 404,repo not found")
//-------------------case 3 : response code = 404------------------------//
fmt.Println("case 3 : response code = 404,repo not found")
repoName = "111"
httpStatusCode, err = apiTest.GetReposManifests(*admin, repoName, tag)
if err != nil {

View File

@ -63,17 +63,18 @@ func initRouters() {
beego.Router("/api/search", &api.SearchAPI{})
beego.Router("/api/projects/:pid([0-9]+)/members/?:mid", &api.ProjectMemberAPI{})
beego.Router("/api/projects/", &api.ProjectAPI{}, "get:List;post:Post")
beego.Router("/api/projects/:id", &api.ProjectAPI{})
beego.Router("/api/projects/:id/publicity", &api.ProjectAPI{}, "put:ToggleProjectPublic")
beego.Router("/api/statistics", &api.StatisticAPI{})
beego.Router("/api/projects/:id([0-9]+)", &api.ProjectAPI{})
beego.Router("/api/projects/:id([0-9]+)/publicity", &api.ProjectAPI{}, "put:ToggleProjectPublic")
beego.Router("/api/projects/:id([0-9]+)/logs/filter", &api.ProjectAPI{}, "post:FilterAccessLog")
beego.Router("/api/projects/:id([0-9]+)/repositories", &api.RepositoryAPI{}, "get:Get")
beego.Router("/api/statistics", &api.StatisticAPI{})
beego.Router("/api/users/?:id", &api.UserAPI{})
beego.Router("/api/users/:id([0-9]+)/password", &api.UserAPI{}, "put:ChangePassword")
beego.Router("/api/internal/syncregistry", &api.InternalAPI{}, "post:SyncRegistry")
beego.Router("/api/repositories", &api.RepositoryAPI{})
beego.Router("/api/repositories/tags", &api.RepositoryAPI{}, "get:GetTags")
beego.Router("/api/repositories/manifests", &api.RepositoryAPI{}, "get:GetManifests")
beego.Router("/api/repositories/signatures", &api.RepositoryAPI{}, "get:GetSignatures")
beego.Router("/api/repositories/*/tags/?:tag", &api.RepositoryAPI{}, "delete:Delete")
beego.Router("/api/repositories/*/tags", &api.RepositoryAPI{}, "get:GetTags")
beego.Router("/api/repositories/*/tags/:tag/manifest", &api.RepositoryAPI{}, "get:GetManifests")
beego.Router("/api/repositories/*/signatures", &api.RepositoryAPI{}, "get:GetSignatures")
beego.Router("/api/jobs/replication/", &api.RepJobAPI{}, "get:List")
beego.Router("/api/jobs/replication/:id([0-9]+)", &api.RepJobAPI{})
beego.Router("/api/jobs/replication/:id([0-9]+)/log", &api.RepJobAPI{}, "get:GetLog")