Merge pull request #750 from zgdxiaoxiao/api-dev

Update api test and swagger.yaml(updated version)
This commit is contained in:
yhua123 2016-09-02 17:19:53 +08:00 committed by GitHub
commit 3a3b4ccecb
9 changed files with 310 additions and 61 deletions

View File

@ -25,8 +25,12 @@ import (
const (
jsonAcceptHeader = "application/json"
testAcceptHeader = "text/plain"
adminName = "admin"
adminPwd = "Harbor12345"
)
var admin, unknownUsr *usrInfo
type api struct {
basePath string
}
@ -57,15 +61,20 @@ func init() {
beego.Router("/api/search/", &SearchAPI{})
beego.Router("/api/projects/", &ProjectAPI{}, "get:List;post:Post;head:Head")
beego.Router("/api/projects/:id/delete", &ProjectAPI{}, "delete:Delete")
beego.Router("/api/projects/:id", &ProjectAPI{}, "delete:Delete;get:Get")
beego.Router("/api/users/:id([0-9]+)/password", &UserAPI{}, "put:ChangePassword")
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")
beego.Router("/api/statistics", &StatisticAPI{})
beego.Router("/api/logs", &LogAPI{})
_ = updateInitPassword(1, "Harbor12345")
//Init user Info
admin = &usrInfo{adminName, adminPwd}
unknownUsr = &usrInfo{"unknown", "unknown"}
}
func request(_sling *sling.Sling, acceptHeader string, authInfo ...usrInfo) (int, []byte, error) {
@ -92,13 +101,17 @@ func request(_sling *sling.Sling, acceptHeader string, authInfo ...usrInfo) (int
//@return []Search
//func (a api) SearchGet (q string) (apilib.Search, error) {
func (a api) SearchGet(q string) (apilib.Search, error) {
_sling := sling.New().Get(a.basePath)
// create path and map variables
path := "/api/search"
_sling = _sling.Path(path)
type QueryParams struct {
Query string `url:"q,omitempty"`
}
_sling = _sling.QueryStruct(&QueryParams{Query: q})
_, body, err := request(_sling, jsonAcceptHeader)
@ -113,11 +126,13 @@ func (a api) SearchGet(q string) (apilib.Search, error) {
//@param project New created project.
//@return void
//func (a api) ProjectsPost (prjUsr usrInfo, project apilib.Project) (int, error) {
func (a api) ProjectsPost(prjUsr usrInfo, project apilib.Project) (int, error) {
func (a api) ProjectsPost(prjUsr usrInfo, project apilib.ProjectReq) (int, error) {
_sling := sling.New().Post(a.basePath)
// create path and map variables
path := "/api/projects/"
_sling = _sling.Path(path)
// body params
@ -136,6 +151,7 @@ func (a api) ProjectsPost(prjUsr usrInfo, project apilib.Project) (int, error) {
func (a api) UsersUserIDPasswordPut(user usrInfo, userID int32, password apilib.Password) int {
_sling := sling.New().Put(a.basePath)
// create path and map variables
path := "/api/users/" + fmt.Sprintf("%d", userID) + "/password"
fmt.Printf("change passwd path: %s\n", path)
@ -144,6 +160,7 @@ func (a api) UsersUserIDPasswordPut(user usrInfo, userID int32, password apilib.
// body params
_sling = _sling.BodyJSON(password)
httpStatusCode, _, _ := request(_sling, jsonAcceptHeader, user)
return httpStatusCode
}
@ -232,12 +249,9 @@ func (a api) ProjectsDelete(prjUsr usrInfo, projectID string) (int, error) {
_sling := sling.New().Delete(a.basePath)
//create api path
path := "api/projects/" + projectID + "/delete"
path := "api/projects/" + projectID
_sling = _sling.Path(path)
//_sling = _sling.BodyJSON(project)
httpStatusCode, body, err := request(_sling, jsonAcceptHeader, prjUsr)
fmt.Println(string(body))
httpStatusCode, _, err := request(_sling, jsonAcceptHeader, prjUsr)
return httpStatusCode, err
}
@ -257,6 +271,23 @@ func (a api) ProjectsHead(prjUsr usrInfo, projectName string) (int, error) {
return httpStatusCode, err
}
//Return specific project detail infomation
func (a api) ProjectsGetByPID(projectID string) (int, apilib.Project, error) {
_sling := sling.New().Get(a.basePath)
//create api path
path := "api/projects/" + projectID
_sling = _sling.Path(path)
var successPayload apilib.Project
httpStatusCode, body, err := request(_sling, jsonAcceptHeader)
if err == nil && httpStatusCode == 200 {
err = json.Unmarshal(body, &successPayload)
}
return httpStatusCode, successPayload, err
}
//Search projects by projectName and isPublic
func (a api) ProjectsGet(projectName string, isPublic int32) (int, []apilib.Project, error) {
_sling := sling.New().Get(a.basePath)
@ -323,17 +354,23 @@ func (a api) ProjectLogsFilter(prjUsr usrInfo, projectID string, accessLog apili
// return httpStatusCode, successPayload, err
}
//-------------------------Member Test---------------------------------------//
//Return relevant role members of projectID
func (a api) GetProjectMembersByProID(prjUsr usrInfo, projectID string) (int, []byte, error) {
_sling := sling.New().Post(a.basePath)
func (a api) GetProjectMembersByProID(prjUsr usrInfo, projectID string) (int, []apilib.User, error) {
_sling := sling.New().Get(a.basePath)
path := "/api/projects/" + projectID + "/members/"
_sling = _sling.Path(path)
httpStatusCode, body, err := request(_sling, jsonAcceptHeader, prjUsr)
return httpStatusCode, body, err
var successPayload []apilib.User
httpStatusCode, body, err := request(_sling, jsonAcceptHeader, prjUsr)
if err == nil && httpStatusCode == 200 {
err = json.Unmarshal(body, &successPayload)
}
return httpStatusCode, successPayload, err
}
//Add project role member accompany with projectID

View File

@ -18,7 +18,7 @@ func TestLogGet(t *testing.T) {
//prepare for test
admin := &usrInfo{"admin", "Harbor12345"}
var project apilib.Project
var project apilib.ProjectReq
project.ProjectName = "my_project"
project.Public = 1
@ -99,17 +99,18 @@ func TestLogGet(t *testing.T) {
//get the project
var projects []apilib.Project
var addProjectID int32
httpStatusCode, projects, err := apiTest.ProjectsGet(project.ProjectName, 1)
if err != nil {
t.Error("Error while search project by proName and isPublic", err.Error())
t.Log(err)
} else {
assert.Equal(int(200), httpStatusCode, "httpStatusCode should be 200")
project.ProjectId = projects[0].ProjectId
addProjectID = projects[0].ProjectId
}
//delete the project
projectID := strconv.Itoa(int(project.ProjectId))
projectID := strconv.Itoa(int(addProjectID))
httpStatusCode, err = apiTest.ProjectsDelete(*admin, projectID)
if err != nil {
t.Error("Error while delete project", err.Error())

54
api/member_test.go Normal file
View File

@ -0,0 +1,54 @@
package api
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/vmware/harbor/tests/apitests/apilib"
)
func TestMemGet(t *testing.T) {
var result []apilib.User
var httpStatusCode int
var err error
assert := assert.New(t)
apiTest := newHarborAPI()
projectID := "1"
fmt.Println("Testing Member Get API")
//-------------------case 1 : response code = 200------------------------//
httpStatusCode, result, err = apiTest.GetProjectMembersByProID(*admin, projectID)
if err != nil {
t.Error("Error whihle get members by projectID", err.Error())
t.Log(err)
} else {
assert.Equal(int(200), httpStatusCode, "httpStatusCode should be 200")
assert.Equal(int(1), result[0].UserId, "User Id should be 1")
assert.Equal("admin", result[0].Username, "User name should be admin")
}
//---------case 2: Response Code=401,User need to log in first.----------//
fmt.Println("case 2: Response Code=401,User need to log in first.")
httpStatusCode, result, err = apiTest.GetProjectMembersByProID(*unknownUsr, projectID)
if err != nil {
t.Error("Error while get members by projectID", err.Error())
t.Log(err)
} else {
assert.Equal(int(401), httpStatusCode, "Case 2: Project creation status should be 401")
}
//------------case 3: Response Code=404,Project does not exist-----------//
fmt.Println("case 3: Response Code=404,Project does not exist")
projectID = "11"
httpStatusCode, result, err = apiTest.GetProjectMembersByProID(*admin, projectID)
if err != nil {
t.Error("Error while get members by projectID", err.Error())
t.Log(err)
} else {
assert.Equal(int(404), httpStatusCode, "Case 3: Project creation status should be 404")
}
fmt.Printf("\n")
}

View File

@ -9,15 +9,11 @@ import (
"time"
)
var admin, unknownUsr *usrInfo
var addProject apilib.Project
func Init() {
admin = &usrInfo{"admin", "Harbor12345"}
unknownUsr = &usrInfo{"unknown", "unknown"}
addProject.ProjectName = "test_project"
addProject.Public = 1
var addProject *apilib.ProjectReq
var addPID int
func InitAddPro() {
addProject = &apilib.ProjectReq{"test_project", 1}
}
func TestAddProject(t *testing.T) {
@ -28,11 +24,11 @@ func TestAddProject(t *testing.T) {
apiTest := newHarborAPI()
//prepare for test
Init()
InitAddPro()
//case 1: admin not login, expect project creation fail.
result, err := apiTest.ProjectsPost(*unknownUsr, addProject)
result, err := apiTest.ProjectsPost(*unknownUsr, *addProject)
if err != nil {
t.Error("Error while creat project", err.Error())
t.Log(err)
@ -44,9 +40,7 @@ func TestAddProject(t *testing.T) {
//case 2: admin successful login, expect project creation success.
fmt.Println("case 2: admin successful login, expect project creation success.")
unknownUsr = admin
result, err = apiTest.ProjectsPost(*admin, addProject)
result, err = apiTest.ProjectsPost(*admin, *addProject)
if err != nil {
t.Error("Error while creat project", err.Error())
t.Log(err)
@ -58,7 +52,7 @@ func TestAddProject(t *testing.T) {
//case 3: duplicate project name, create project fail
fmt.Println("case 3: duplicate project name, create project fail")
result, err = apiTest.ProjectsPost(*admin, addProject)
result, err = apiTest.ProjectsPost(*admin, *addProject)
if err != nil {
t.Error("Error while creat project", err.Error())
t.Log(err)
@ -66,12 +60,25 @@ func TestAddProject(t *testing.T) {
assert.Equal(int(409), result, "Case 3: Project creation status should be 409")
//t.Log(result)
}
//case 4: reponse code = 400 : Project name is illegal in length
fmt.Println("case 4 : reponse code = 400 : Project name is illegal in length ")
result, err = apiTest.ProjectsPost(*admin, apilib.ProjectReq{"t", 1})
if err != nil {
t.Error("Error while creat project", err.Error())
t.Log(err)
} else {
assert.Equal(int(400), result, "case 4 : reponse code = 400 : Project name is illegal in length ")
}
fmt.Printf("\n")
}
func TestProGet(t *testing.T) {
fmt.Println("\nTest for Project GET API")
//Get project by proName
func TestProGetByName(t *testing.T) {
fmt.Println("\nTest for Project GET API by project name")
assert := assert.New(t)
apiTest := newHarborAPI()
@ -85,10 +92,11 @@ func TestProGet(t *testing.T) {
t.Log(err)
} else {
assert.Equal(int(200), httpStatusCode, "httpStatusCode should be 200")
assert.Equal(addProject.ProjectName, result[0].ProjectName, "Project name is wrong")
assert.Equal(int32(1), result[0].Public, "Public is wrong")
//find add projectID
addProject.ProjectId = int32(result[0].ProjectId)
addPID = int(result[0].ProjectId)
}
//----------------------------case 2 : Response Code=401:is_public=0----------------------------//
fmt.Println("case 2: respose code:401,isPublic = 0")
httpStatusCode, result, err = apiTest.ProjectsGet("library", 0)
@ -98,10 +106,31 @@ func TestProGet(t *testing.T) {
} else {
assert.Equal(int(401), httpStatusCode, "httpStatusCode should be 200")
}
fmt.Printf("\n")
}
//Get project by proID
func TestProGetByID(t *testing.T) {
fmt.Println("\nTest for Project GET API by project id")
assert := assert.New(t)
apiTest := newHarborAPI()
var result apilib.Project
projectID := strconv.Itoa(addPID)
//----------------------------case 1 : Response Code=200----------------------------//
fmt.Println("case 1: respose code:200")
httpStatusCode, result, err := apiTest.ProjectsGetByPID(projectID)
if err != nil {
t.Error("Error while search project by proID", err.Error())
t.Log(err)
} else {
assert.Equal(int(200), httpStatusCode, "httpStatusCode should be 200")
assert.Equal(addProject.ProjectName, result.ProjectName, "ProjectName is wrong")
assert.Equal(int32(1), result.Public, "Public is wrong")
}
fmt.Printf("\n")
}
func TestDeleteProject(t *testing.T) {
fmt.Println("\nTesting Delete Project(ProjectsPost) API")
@ -109,23 +138,53 @@ func TestDeleteProject(t *testing.T) {
apiTest := newHarborAPI()
projectID := strconv.Itoa(int(addProject.ProjectId))
//--------------------------case 1: Response Code=200---------------------------------//
projectID := strconv.Itoa(addPID)
httpStatusCode, err := apiTest.ProjectsDelete(*admin, projectID)
//--------------------------case 1: Response Code=401,User need to log in first.-----------------------//
fmt.Println("case 1: Response Code=401,User need to log in first.")
httpStatusCode, err := apiTest.ProjectsDelete(*unknownUsr, projectID)
if err != nil {
t.Error("Error while delete project", err.Error())
t.Log(err)
} else {
assert.Equal(int(200), httpStatusCode, "Case 1: Project creation status should be 200")
//t.Log(result)
assert.Equal(int(401), httpStatusCode, "Case 1: Project creation status should be 401")
}
//--------------------------case 2: Response Code=200---------------------------------//
fmt.Println("case2: respose code:200")
httpStatusCode, err = apiTest.ProjectsDelete(*admin, projectID)
if err != nil {
t.Error("Error while delete project", err.Error())
t.Log(err)
} else {
assert.Equal(int(200), httpStatusCode, "Case 2: Project creation status should be 200")
}
//--------------------------case 3: Response Code=404,Project does not exist---------------------------------//
fmt.Println("case 3: Response Code=404,Project does not exist")
projectID = "11"
httpStatusCode, err = apiTest.ProjectsDelete(*admin, projectID)
if err != nil {
t.Error("Error while delete project", err.Error())
t.Log(err)
} else {
assert.Equal(int(404), httpStatusCode, "Case 3: Project creation status should be 404")
}
//--------------------------case 4: Response Code=400,Invalid project id.---------------------------------//
fmt.Println("case 4: Response Code=400,Invalid project id.")
projectID = "cc"
httpStatusCode, err = apiTest.ProjectsDelete(*admin, projectID)
if err != nil {
t.Error("Error while delete project", err.Error())
t.Log(err)
} else {
assert.Equal(int(400), httpStatusCode, "Case 4: Project creation status should be 400")
}
fmt.Printf("\n")
}
func TestProHead(t *testing.T) {
Init()
fmt.Println("\nTest for Project HEAD API")
assert := assert.New(t)

View File

@ -34,7 +34,7 @@ func TestStatisticGet(t *testing.T) {
totalProCount = result.TotalProjectCount
}
//post project
var project apilib.Project
var project apilib.ProjectReq
project.ProjectName = "statistic_project"
project.Public = 1
@ -65,17 +65,18 @@ func TestStatisticGet(t *testing.T) {
//get the project
var projects []apilib.Project
var addProjectID int32
httpStatusCode, projects, err := apiTest.ProjectsGet(project.ProjectName, 1)
if err != nil {
t.Error("Error while search project by proName and isPublic", err.Error())
t.Log(err)
} else {
assert.Equal(int(200), httpStatusCode, "httpStatusCode should be 200")
project.ProjectId = projects[0].ProjectId
addProjectID = projects[0].ProjectId
}
//delete the project
projectID := strconv.Itoa(int(project.ProjectId))
projectID := strconv.Itoa(int(addProjectID))
httpStatusCode, err = apiTest.ProjectsDelete(*admin, projectID)
if err != nil {
t.Error("Error while delete project", err.Error())

View File

@ -123,7 +123,7 @@ paths:
description: New created project.
required: true
schema:
$ref: '#/definitions/Project'
$ref: '#/definitions/ProjectReq'
tags:
- Products
responses:
@ -155,13 +155,37 @@ paths:
200:
description: Return matched project information.
schema:
type: array
items:
$ref: '#/definitions/Project'
401:
description: User need to log in first.
500:
description: Internal errors.
delete:
summary: Delete project by projectID
description: |
This endpoint is aimed to delete project by project ID.
parameters:
- name: project_id
in: path
description: Project ID of project which will be deleted.
required: true
type: integer
format: int64
tags:
- Products
responses:
200:
description: Project is deleted successfully.
400:
description: Invalid project id.
403:
description: User need to log in first.
404:
description: Project does not exist.
412:
description: Project contains policies, can not be deleted.
500:
description: Internal errors.
/projects/{project_id}/publicity:
put:
summary: Update properties for a selected project.
@ -1290,6 +1314,16 @@ definitions:
project_public:
type: integer
description: The flag to indicate the publicity of the project that the repository belongs to (1 is public, 0 is not)
ProjectReq:
type: object
properties:
project_name:
type: string
description: The name of the project.
public:
type: integer
format: int
description: The public status of the project.
Project:
type: object
properties:
@ -1301,7 +1335,7 @@ definitions:
type: integer
format: int32
description: The owner ID of the project always means the creator of the project.
project_name:
name:
type: string
description: The name of the project.
creation_time:
@ -1322,8 +1356,8 @@ definitions:
type: string
description: The owner name of the project.
public:
type: boolean
format: boolean
type: integer
format: int
description: The public status of the project.
togglable:
type: boolean
@ -1348,7 +1382,7 @@ definitions:
properties:
user_id:
type: integer
format: int32
format: int
description: The ID of the user.
username:
type: string
@ -1363,6 +1397,22 @@ definitions:
deleted:
type: integer
format: int32
role_name:
type: string
role_id:
type: integer
format: int
has_admin_role:
type: integer
format: int
reset_uuid:
type: string
Salt:
type: string
creation_time:
type: string
update_time:
type: string
Password:
type: object
properties:
@ -1637,3 +1687,4 @@ definitions:
password:
type: string
description: The target server password.

View File

@ -31,7 +31,7 @@ type Project struct {
OwnerId int32 `json:"owner_id,omitempty"`
// The name of the project.
ProjectName string `json:"project_name,omitempty"`
ProjectName string `json:"name,omitempty"`
// The creation time of the project.
CreationTime string `json:"creation_time,omitempty"`

View File

@ -0,0 +1,32 @@
/*
* Harbor API
*
* These APIs provide services for manipulating Harbor project.
*
* OpenAPI spec version: 0.3.0
*
* Generated by: https://github.com/swagger-api/swagger-codegen.git
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package apilib
type ProjectReq struct {
// The name of the project.
ProjectName string `json:"project_name,omitempty"`
// The public status of the project.
Public int32 `json:"public,omitempty"`
}

View File

@ -25,7 +25,7 @@ package apilib
type User struct {
// The ID of the user.
UserId int32 `json:"user_id,omitempty"`
UserId int `json:"user_id,omitempty"`
Username string `json:"username,omitempty"`
@ -38,4 +38,18 @@ type User struct {
Comment string `json:"comment,omitempty"`
Deleted int32 `json:"deleted,omitempty"`
RoleName string `json:"role_name,omitempty"`
RoleId int32 `json:"role_id,omitempty"`
HasAdminRole int32 `json:"has_admin_role,omitempty"`
ResetUuid string `json:"reset_uuid,omitempty"`
Salt string `json:"Salt,omitempty"`
CreationTime string `json:"creation_time,omitempty"`
UpdateTime string `json:"update_time,omitempty"`
}