mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-22 10:15:35 +01:00
add api testing framework
This commit is contained in:
parent
08722e2166
commit
74702a0be7
42
.travis.yml
42
.travis.yml
@ -9,27 +9,25 @@ go_import_path: github.com/vmware/harbor
|
||||
|
||||
services:
|
||||
- docker
|
||||
- mysql
|
||||
|
||||
dist: trusty
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- mysql-server-5.6
|
||||
- mysql-client-core-5.6
|
||||
- mysql-client-5.6
|
||||
|
||||
env:
|
||||
DB_HOST: 127.0.0.1
|
||||
DB_PORT: 3306
|
||||
DB_USR: root
|
||||
DB_PWD:
|
||||
DB_PWD: root123
|
||||
MYSQL_HOST: localhost
|
||||
MYSQL_PORT: 3306
|
||||
MYSQL_USR: root
|
||||
MYSQL_PWD: root123
|
||||
DOCKER_COMPOSE_VERSION: 1.7.1
|
||||
HARBOR_ADMIN: admin
|
||||
HARBOR_ADMIN_PASSWD: Harbor12345
|
||||
UI_SECRET: tempString
|
||||
MAX_JOB_WORKERS: 3
|
||||
SECRET_KEY: 1234567890123456
|
||||
SECRET_KEY: 1234567890123456
|
||||
AUTH_MODE: db_auth
|
||||
|
||||
before_install:
|
||||
- sudo ./tests/hostcfg.sh
|
||||
@ -56,8 +54,8 @@ install:
|
||||
- go get -d github.com/go-sql-driver/mysql
|
||||
- go get github.com/golang/lint/golint
|
||||
- go get github.com/GeertJohan/fgt
|
||||
- sudo apt-get install -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" docker-engine=1.11.1-0~trusty
|
||||
- sudo rm /usr/local/bin/docker-compose
|
||||
# - sudo apt-get install -y --force-yes -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" docker-engine=1.11.1-0~trusty
|
||||
# - sudo rm /usr/local/bin/docker-compose
|
||||
- curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
|
||||
- chmod +x docker-compose
|
||||
- sudo mv docker-compose /usr/local/bin
|
||||
@ -70,21 +68,27 @@ install:
|
||||
|
||||
before_script:
|
||||
# create tables and load data
|
||||
- mysql < ./Deploy/db/registry.sql -uroot --verbose
|
||||
# - mysql < ./Deploy/db/registry.sql -uroot --verbose
|
||||
|
||||
script:
|
||||
- go list ./... | grep -v -E 'vendor|tests' | xargs -L1 fgt golint
|
||||
- go list ./... | grep -v -E 'vendor|tests' | xargs -L1 go vet
|
||||
script:
|
||||
- sudo ./tests/testprepare.sh
|
||||
- docker-compose -f Deploy/docker-compose.test.yml up -d
|
||||
- go list ./... | grep -v -E 'vendor|tests|api' | xargs -L1 fgt golint
|
||||
- go list ./... | grep -v -E 'vendor|tests|api' | xargs -L1 go vet
|
||||
- IP=`ip addr s eth0 |grep "inet "|awk '{print $2}' |awk -F "/" '{print $1}'`
|
||||
- export MYSQL_HOST=$IP
|
||||
- export REGISTRY_URL=http://$IP:5000
|
||||
- echo $REGISTRY_URL
|
||||
- ./Deploy/coverage4gotest.sh
|
||||
- goveralls -coverprofile=profile.cov -service=travis-ci
|
||||
|
||||
- docker-compose -f Deploy/docker-compose.test.yml down
|
||||
|
||||
- docker-compose -f Deploy/docker-compose.yml up -d
|
||||
|
||||
- docker ps
|
||||
- go run tests/startuptest.go http://localhost/
|
||||
- go run tests/userlogintest.go -name ${HARBOR_ADMIN} -passwd ${HARBOR_ADMIN_PASSWD}
|
||||
|
||||
|
||||
# test for API
|
||||
- sudo ./tests/testprepare.sh
|
||||
- go test -v ./tests/apitests
|
||||
# - sudo ./tests/testprepare.sh
|
||||
# - go test -v ./tests/apitests
|
||||
|
312
api/harborapi_test.go
Normal file
312
api/harborapi_test.go
Normal file
@ -0,0 +1,312 @@
|
||||
//These APIs provide services for manipulating Harbor project.
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http/httptest"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/vmware/harbor/tests/apitests/apilib"
|
||||
"github.com/vmware/harbor/dao"
|
||||
"github.com/vmware/harbor/models"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/dghubble/sling"
|
||||
|
||||
//for test env prepare
|
||||
_ "github.com/vmware/harbor/auth/db"
|
||||
_ "github.com/vmware/harbor/auth/ldap"
|
||||
)
|
||||
|
||||
type api struct {
|
||||
basePath string
|
||||
}
|
||||
|
||||
func newHarborAPI() *api {
|
||||
return &api{
|
||||
basePath: "",
|
||||
}
|
||||
}
|
||||
|
||||
func newHarborAPIWithBasePath(basePath string) *api {
|
||||
return &api{
|
||||
basePath: basePath,
|
||||
}
|
||||
}
|
||||
|
||||
type usrInfo struct {
|
||||
Name string
|
||||
Passwd string
|
||||
}
|
||||
|
||||
func init() {
|
||||
dao.InitDB()
|
||||
_, file, _, _ := runtime.Caller(1)
|
||||
apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".."+string(filepath.Separator))))
|
||||
beego.BConfig.WebConfig.Session.SessionOn = true
|
||||
beego.TestBeegoInit(apppath)
|
||||
|
||||
beego.Router("/api/search/", &SearchAPI{})
|
||||
beego.Router("/api/projects/", &ProjectAPI{}, "get:List;post:Post")
|
||||
beego.Router("/api/users/:id([0-9]+)/password", &UserAPI{}, "put:ChangePassword")
|
||||
|
||||
_ = updateInitPassword(1, "Harbor12345")
|
||||
|
||||
}
|
||||
|
||||
//Search for projects and repositories
|
||||
//Implementation Notes
|
||||
//The Search endpoint returns information about the projects and repositories
|
||||
//offered at public status or related to the current logged in user.
|
||||
//The response includes the project and repository list in a proper display order.
|
||||
//@param q Search parameter for project and repository name.
|
||||
//@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})
|
||||
|
||||
accepts := []string{"application/json", "text/plain"}
|
||||
for key := range accepts {
|
||||
_sling = _sling.Set("Accept", accepts[key])
|
||||
break // only use the first Accept
|
||||
}
|
||||
|
||||
req, err := _sling.Request()
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
beego.BeeApp.Handlers.ServeHTTP(w, req)
|
||||
|
||||
body, err := ioutil.ReadAll(w.Body)
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
|
||||
var successPayload = new(apilib.Search)
|
||||
err = json.Unmarshal(body, &successPayload)
|
||||
return *successPayload, err
|
||||
}
|
||||
|
||||
//Create a new project.
|
||||
//Implementation Notes
|
||||
//This endpoint is for user to create a new project.
|
||||
//@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) {
|
||||
|
||||
_sling := sling.New().Post(a.basePath)
|
||||
|
||||
// create path and map variables
|
||||
path := "/api/projects/"
|
||||
|
||||
_sling = _sling.Path(path)
|
||||
|
||||
// accept header
|
||||
accepts := []string{"application/json", "text/plain"}
|
||||
for key := range accepts {
|
||||
_sling = _sling.Set("Accept", accepts[key])
|
||||
break // only use the first Accept
|
||||
}
|
||||
|
||||
// body params
|
||||
_sling = _sling.BodyJSON(project)
|
||||
//fmt.Printf("project post req: %+v\n", _sling)
|
||||
req, err := _sling.Request()
|
||||
req.SetBasicAuth(prjUsr.Name, prjUsr.Passwd)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
beego.BeeApp.Handlers.ServeHTTP(w, req)
|
||||
|
||||
return w.Code, err
|
||||
}
|
||||
|
||||
//Change password
|
||||
//Implementation Notes
|
||||
//Change the password on a user that already exists.
|
||||
//@param userID user ID
|
||||
//@param password user old and new password
|
||||
//@return error
|
||||
//func (a api) UsersUserIDPasswordPut (user usrInfo, userID int32, password apilib.Password) int {
|
||||
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)
|
||||
fmt.Printf("password %+v\n", password)
|
||||
_sling = _sling.Path(path)
|
||||
|
||||
// accept header
|
||||
accepts := []string{"application/json", "text/plain"}
|
||||
for key := range accepts {
|
||||
_sling = _sling.Set("Accept", accepts[key])
|
||||
break // only use the first Accept
|
||||
}
|
||||
|
||||
// body params
|
||||
_sling = _sling.BodyJSON(password)
|
||||
fmt.Printf("project post req: %+v\n", _sling)
|
||||
req, err := _sling.Request()
|
||||
req.SetBasicAuth(user.Name, user.Passwd)
|
||||
fmt.Printf("project post req: %+v\n", req)
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
beego.BeeApp.Handlers.ServeHTTP(w, req)
|
||||
|
||||
return w.Code
|
||||
|
||||
}
|
||||
|
||||
////Delete a repository or a tag in a repository.
|
||||
////Delete a repository or a tag in a repository.
|
||||
////This endpoint let user delete repositories and tags with repo name and tag.\n
|
||||
////@param repoName The name of repository which will be deleted.
|
||||
////@param tag Tag of a repository.
|
||||
////@return void
|
||||
////func (a HarborAPI) RepositoriesDelete(prjUsr UsrInfo, repoName string, tag string) (int, error) {
|
||||
//func (a HarborAPI) RepositoriesDelete(prjUsr UsrInfo, repoName string, tag string) (int, error) {
|
||||
// _sling := sling.New().Delete(a.basePath)
|
||||
|
||||
// // create path and map variables
|
||||
// path := "/api/repositories"
|
||||
|
||||
// _sling = _sling.Path(path)
|
||||
|
||||
// type QueryParams struct {
|
||||
// RepoName string `url:"repo_name,omitempty"`
|
||||
// Tag string `url:"tag,omitempty"`
|
||||
// }
|
||||
|
||||
// _sling = _sling.QueryStruct(&QueryParams{RepoName: repoName, Tag: tag})
|
||||
// // accept header
|
||||
// accepts := []string{"application/json", "text/plain"}
|
||||
// for key := range accepts {
|
||||
// _sling = _sling.Set("Accept", accepts[key])
|
||||
// break // only use the first Accept
|
||||
// }
|
||||
|
||||
// req, err := _sling.Request()
|
||||
// req.SetBasicAuth(prjUsr.Name, prjUsr.Passwd)
|
||||
// //fmt.Printf("request %+v", req)
|
||||
|
||||
// client := &http.Client{}
|
||||
// httpResponse, err := client.Do(req)
|
||||
// defer httpResponse.Body.Close()
|
||||
|
||||
// if err != nil {
|
||||
// // handle error
|
||||
// }
|
||||
// return httpResponse.StatusCode, err
|
||||
//}
|
||||
|
||||
//Return projects created by Harbor
|
||||
//func (a HarborApi) ProjectsGet (projectName string, isPublic int32) ([]Project, error) {
|
||||
// }
|
||||
|
||||
//Check if the project name user provided already exists.
|
||||
//func (a HarborApi) ProjectsHead (projectName string) (error) {
|
||||
//}
|
||||
|
||||
//Get access logs accompany with a relevant project.
|
||||
//func (a HarborApi) ProjectsProjectIdLogsFilterPost (projectId int32, accessLog AccessLog) ([]AccessLog, error) {
|
||||
//}
|
||||
|
||||
//Return a project's relevant role members.
|
||||
//func (a HarborApi) ProjectsProjectIdMembersGet (projectId int32) ([]Role, error) {
|
||||
//}
|
||||
|
||||
//Add project role member accompany with relevant project and user.
|
||||
//func (a HarborApi) ProjectsProjectIdMembersPost (projectId int32, roles RoleParam) (error) {
|
||||
//}
|
||||
|
||||
//Delete project role members accompany with relevant project and user.
|
||||
//func (a HarborApi) ProjectsProjectIdMembersUserIdDelete (projectId int32, userId int32) (error) {
|
||||
//}
|
||||
|
||||
//Return role members accompany with relevant project and user.
|
||||
//func (a HarborApi) ProjectsProjectIdMembersUserIdGet (projectId int32, userId int32) ([]Role, error) {
|
||||
//}
|
||||
|
||||
//Update project role members accompany with relevant project and user.
|
||||
//func (a HarborApi) ProjectsProjectIdMembersUserIdPut (projectId int32, userId int32, roles RoleParam) (error) {
|
||||
//}
|
||||
|
||||
//Update properties for a selected project.
|
||||
//func (a HarborApi) ProjectsProjectIdPut (projectId int32, project Project) (error) {
|
||||
//}
|
||||
|
||||
//Get repositories accompany with relevant project and repo name.
|
||||
//func (a HarborApi) RepositoriesGet (projectId int32, q string) ([]Repository, error) {
|
||||
//}
|
||||
|
||||
//Get manifests of a relevant repository.
|
||||
//func (a HarborApi) RepositoriesManifestGet (repoName string, tag string) (error) {
|
||||
//}
|
||||
|
||||
//Get tags of a relevant repository.
|
||||
//func (a HarborApi) RepositoriesTagsGet (repoName string) (error) {
|
||||
//}
|
||||
|
||||
//Get registered users of Harbor.
|
||||
//func (a HarborApi) UsersGet (userName string) ([]User, error) {
|
||||
//}
|
||||
|
||||
//Creates a new user account.
|
||||
//func (a HarborApi) UsersPost (user User) (error) {
|
||||
//}
|
||||
|
||||
//Mark a registered user as be removed.
|
||||
//func (a HarborApi) UsersUserIdDelete (userId int32) (error) {
|
||||
//}
|
||||
|
||||
//Update a registered user to change to be an administrator of Harbor.
|
||||
//func (a HarborApi) UsersUserIdPut (userId int32) (error) {
|
||||
//}
|
||||
|
||||
func updateInitPassword(userID int, password string) error {
|
||||
queryUser := models.User{UserID: userID}
|
||||
user, err := dao.GetUser(queryUser)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to get user, userID: %d %v", userID, err)
|
||||
}
|
||||
if user == nil {
|
||||
return fmt.Errorf("User id: %d does not exist.", userID)
|
||||
}
|
||||
if user.Salt == "" {
|
||||
salt, err := dao.GenerateRandomString()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to generate salt for encrypting password, %v", err)
|
||||
}
|
||||
|
||||
user.Salt = salt
|
||||
user.Password = password
|
||||
err = dao.ChangeUserPassword(*user)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to update user encrypted password, userID: %d, err: %v", userID, err)
|
||||
}
|
||||
|
||||
} else {
|
||||
}
|
||||
return nil
|
||||
}
|
65
api/project_test.go
Normal file
65
api/project_test.go
Normal file
@ -0,0 +1,65 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/vmware/harbor/tests/apitests/apilib"
|
||||
)
|
||||
|
||||
func TestAddProject(t *testing.T) {
|
||||
|
||||
fmt.Println("Testing Add Project(ProjectsPost) API")
|
||||
assert := assert.New(t)
|
||||
|
||||
apiTest := newHarborAPI()
|
||||
|
||||
//prepare for test
|
||||
|
||||
admin := &usrInfo{"admin", "Harbor12345"}
|
||||
|
||||
prjUsr := &usrInfo{"unknown", "unknown"}
|
||||
|
||||
var project apilib.Project
|
||||
project.ProjectName = "test_project"
|
||||
project.Public = true
|
||||
|
||||
//case 1: admin not login, expect project creation fail.
|
||||
|
||||
result, err := apiTest.ProjectsPost(*prjUsr, project)
|
||||
if err != nil {
|
||||
t.Error("Error while creat project", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
assert.Equal(result, int(401), "Case 1: Project creation status should be 401")
|
||||
//t.Log(result)
|
||||
}
|
||||
|
||||
//case 2: admin successful login, expect project creation success.
|
||||
fmt.Println("case 2: admin successful login, expect project creation success.")
|
||||
|
||||
prjUsr = admin
|
||||
|
||||
result, err = apiTest.ProjectsPost(*prjUsr, project)
|
||||
if err != nil {
|
||||
t.Error("Error while creat project", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
assert.Equal(result, int(201), "Case 2: Project creation status should be 201")
|
||||
//t.Log(result)
|
||||
}
|
||||
|
||||
//case 3: duplicate project name, create project fail
|
||||
fmt.Println("case 3: duplicate project name, create project fail")
|
||||
|
||||
result, err = apiTest.ProjectsPost(*prjUsr, project)
|
||||
if err != nil {
|
||||
t.Error("Error while creat project", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
assert.Equal(result, int(409), "Case 3: Project creation status should be 409")
|
||||
//t.Log(result)
|
||||
}
|
||||
|
||||
}
|
32
api/search_test.go
Normal file
32
api/search_test.go
Normal file
@ -0,0 +1,32 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/vmware/harbor/tests/apitests/apilib"
|
||||
)
|
||||
|
||||
func TestSearch(t *testing.T) {
|
||||
fmt.Println("Testing Search(SearchGet) API")
|
||||
assert := assert.New(t)
|
||||
|
||||
apiTest := newHarborAPI()
|
||||
var result apilib.Search
|
||||
result, err := apiTest.SearchGet("library")
|
||||
//fmt.Printf("%+v\n", result)
|
||||
if err != nil {
|
||||
t.Error("Error while search project or repository", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
assert.Equal(result.Projects[0].ProjectID, int32(1), "Project id should be equal")
|
||||
assert.Equal(result.Projects[0].ProjectName, "library", "Project name should be library")
|
||||
assert.Equal(result.Projects[0].Public, int32(1), "Project public status should be 1 (true)")
|
||||
//t.Log(result)
|
||||
}
|
||||
//if result.Response.StatusCode != 200 {
|
||||
// t.Log(result.Response)
|
||||
//}
|
||||
|
||||
}
|
@ -13,8 +13,9 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package HarborAPI
|
||||
package apilib
|
||||
|
||||
//AccessLog for go test
|
||||
type AccessLog struct {
|
||||
Username string `json:"username,omitempty"`
|
||||
Keywords string `json:"keywords,omitempty"`
|
||||
|
@ -1,6 +1,6 @@
|
||||
//Package HarborAPI
|
||||
//Package apilib
|
||||
//These APIs provide services for manipulating Harbor project.
|
||||
package HarborAPI
|
||||
package apilib
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
@ -1,5 +1,5 @@
|
||||
// HarborLogout.go
|
||||
package HarborAPI
|
||||
package apilib
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
@ -1,5 +1,5 @@
|
||||
// HarborLogon.go
|
||||
package HarborAPI
|
||||
package apilib
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
|
13
tests/apitests/apilib/password.go
Normal file
13
tests/apitests/apilib/password.go
Normal file
@ -0,0 +1,13 @@
|
||||
package apilib
|
||||
|
||||
import ()
|
||||
|
||||
//Password for go test
|
||||
type Password struct {
|
||||
|
||||
// The user's existing password.
|
||||
OldPassword string `json:"old_password,omitempty"`
|
||||
|
||||
// New password for marking as to be updated.
|
||||
NewPassword string `json:"new_password,omitempty"`
|
||||
}
|
@ -1,14 +1,15 @@
|
||||
package HarborAPI
|
||||
package apilib
|
||||
|
||||
import ()
|
||||
|
||||
//Project for go test
|
||||
type Project struct {
|
||||
ProjectId int32 `json:"id,omitempty"`
|
||||
OwnerId int32 `json:"owner_id,omitempty"`
|
||||
ProjectID int32 `json:"id,omitempty"`
|
||||
OwnerID int32 `json:"owner_id,omitempty"`
|
||||
ProjectName string `json:"project_name,omitempty"`
|
||||
CreationTime string `json:"creation_time,omitempty"`
|
||||
Deleted int32 `json:"deleted,omitempty"`
|
||||
UserId int32 `json:"user_id,omitempty"`
|
||||
UserID int32 `json:"user_id,omitempty"`
|
||||
OwnerName string `json:"owner_name,omitempty"`
|
||||
Public bool `json:"public,omitempty"`
|
||||
Togglable bool `json:"togglable,omitempty"`
|
||||
|
@ -1,9 +1,8 @@
|
||||
package HarborAPI
|
||||
|
||||
import ()
|
||||
package apilib
|
||||
|
||||
//Project4Search ...
|
||||
type Project4Search struct {
|
||||
ProjectId int32 `json:"id,omitempty"`
|
||||
ProjectID int32 `json:"id,omitempty"`
|
||||
ProjectName string `json:"name,omitempty"`
|
||||
Public int32 `json:"public,omitempty"`
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
package HarborAPI
|
||||
package apilib
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
//Repository ...
|
||||
type Repository struct {
|
||||
Id string `json:"id,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Parent string `json:"parent,omitempty"`
|
||||
Created time.Time `json:"created,omitempty"`
|
||||
DurationDays string `json:"duration_days,omitempty"`
|
||||
|
@ -1,7 +1,10 @@
|
||||
package HarborAPI
|
||||
package apilib
|
||||
|
||||
import ()
|
||||
|
||||
//Repository4Search ...
|
||||
type Repository4Search struct {
|
||||
ProjectId int32 `json:"project_id,omitempty"`
|
||||
ProjectID int32 `json:"project_id,omitempty"`
|
||||
ProjectName string `json:"project_name,omitempty"`
|
||||
ProjectPublic int32 `json:"project_public,omitempty"`
|
||||
RepoName string `json:"repository_name,omitempty"`
|
||||
|
@ -1,7 +1,8 @@
|
||||
package HarborAPI
|
||||
package apilib
|
||||
|
||||
//Role ...
|
||||
type Role struct {
|
||||
RoleId int32 `json:"role_id,omitempty"`
|
||||
RoleID int32 `json:"role_id,omitempty"`
|
||||
RoleCode string `json:"role_code,omitempty"`
|
||||
RoleName string `json:"role_name,omitempty"`
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package HarborAPI
|
||||
package apilib
|
||||
|
||||
//RoleParam ...
|
||||
type RoleParam struct {
|
||||
Roles []int32 `json:"roles,omitempty"`
|
||||
UserName string `json:"user_name,omitempty"`
|
||||
|
@ -1,7 +1,8 @@
|
||||
package HarborAPI
|
||||
package apilib
|
||||
|
||||
import ()
|
||||
|
||||
//Search ...
|
||||
type Search struct {
|
||||
Projects []Project4Search `json:"project,omitempty"`
|
||||
Repositories []Repository4Search `json:"repository,omitempty"`
|
||||
|
@ -1,7 +1,8 @@
|
||||
package HarborAPI
|
||||
package apilib
|
||||
|
||||
//User ...
|
||||
type User struct {
|
||||
UserId int32 `json:"user_id,omitempty"`
|
||||
UserID int32 `json:"user_id,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
Email string `json:"email,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
|
@ -1,95 +0,0 @@
|
||||
package HarborAPItest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
"github.com/vmware/harbor/tests/apitests/apilib"
|
||||
)
|
||||
|
||||
func TestAddProject(t *testing.T) {
|
||||
|
||||
fmt.Println("Test for Project Add (ProjectsPost) API")
|
||||
assert := assert.New(t)
|
||||
|
||||
apiTest := HarborAPI.NewHarborAPI()
|
||||
|
||||
//prepare for test
|
||||
adminEr := &HarborAPI.UsrInfo{"admin", "Harbor1234"}
|
||||
admin := &HarborAPI.UsrInfo{"admin", "Harbor12345"}
|
||||
|
||||
prjUsr := &HarborAPI.UsrInfo{"unknown", "unknown"}
|
||||
|
||||
var project HarborAPI.Project
|
||||
project.ProjectName = "testproject"
|
||||
project.Public = true
|
||||
|
||||
//case 1: admin login fail, expect project creation fail.
|
||||
fmt.Println("case 1: admin login fail, expect project creation fail.")
|
||||
resault, err := apiTest.HarborLogin(*adminEr)
|
||||
if err != nil {
|
||||
t.Error("Error while admin login", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
assert.Equal(resault, int(401), "Admin login status should be 401")
|
||||
//t.Log(resault)
|
||||
}
|
||||
|
||||
resault, err = apiTest.ProjectsPost(*prjUsr, project)
|
||||
if err != nil {
|
||||
t.Error("Error while creat project", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
assert.Equal(resault, int(401), "Case 1: Project creation status should be 401")
|
||||
//t.Log(resault)
|
||||
}
|
||||
|
||||
//case 2: admin successful login, expect project creation success.
|
||||
fmt.Println("case 2: admin successful login, expect project creation success.")
|
||||
resault, err = apiTest.HarborLogin(*admin)
|
||||
if err != nil {
|
||||
t.Error("Error while admin login", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
assert.Equal(resault, int(200), "Admin login status should be 200")
|
||||
//t.Log(resault)
|
||||
}
|
||||
if resault != 200 {
|
||||
t.Log(resault)
|
||||
} else {
|
||||
prjUsr = admin
|
||||
}
|
||||
|
||||
resault, err = apiTest.ProjectsPost(*prjUsr, project)
|
||||
if err != nil {
|
||||
t.Error("Error while creat project", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
assert.Equal(resault, int(201), "Case 2: Project creation status should be 201")
|
||||
//t.Log(resault)
|
||||
}
|
||||
|
||||
//case 3: duplicate project name, create project fail
|
||||
fmt.Println("case 3: duplicate project name, create project fail")
|
||||
resault, err = apiTest.ProjectsPost(*prjUsr, project)
|
||||
if err != nil {
|
||||
t.Error("Error while creat project", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
assert.Equal(resault, int(409), "Case 3: Project creation status should be 409")
|
||||
//t.Log(resault)
|
||||
}
|
||||
|
||||
//resault1, err := apiTest.HarborLogout()
|
||||
//if err != nil {
|
||||
// t.Error("Error while admin logout", err.Error())
|
||||
// t.Log(err)
|
||||
//} else {
|
||||
// assert.Equal(resault1, int(200), "Admin logout status")
|
||||
// //t.Log(resault)
|
||||
//}
|
||||
//if resault1 != 200 {
|
||||
// t.Log(resault)
|
||||
//}
|
||||
|
||||
}
|
@ -1,130 +0,0 @@
|
||||
package HarborAPItest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/vmware/harbor/tests/apitests/apilib"
|
||||
)
|
||||
|
||||
func TestRepositoryDelete(t *testing.T) {
|
||||
fmt.Println("Test for Project Delete (ProjectDelete) API")
|
||||
assert := assert.New(t)
|
||||
|
||||
//prepare for test
|
||||
adminEr := &HarborAPI.UsrInfo{"admin", "Harbor1234"}
|
||||
admin := &HarborAPI.UsrInfo{"admin", "Harbor12345"}
|
||||
prjUsr := &HarborAPI.UsrInfo{"unknown", "unknown"}
|
||||
|
||||
fmt.Println("Checking repository status...")
|
||||
apiTest := HarborAPI.NewHarborAPI()
|
||||
var searchResault HarborAPI.Search
|
||||
searchResault, err := apiTest.SearchGet("library")
|
||||
//fmt.Printf("%+v\n", resault)
|
||||
|
||||
if err != nil {
|
||||
t.Error("Error while search project or repository", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
//assert.Equal(searchResault.Repositories[0].RepoName, "library/docker", "1st repo name should be")
|
||||
if !assert.Equal(searchResault.Repositories[0].RepoName, "library/docker", "1st repo name should be") {
|
||||
t.Error("fail to find repo 'library/docker'", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
fmt.Println("repo 'library/docker' exit")
|
||||
}
|
||||
//assert.Equal(searchResault.Repositories[1].RepoName, "library/hello-world", "2nd repo name should be")
|
||||
if !assert.Equal(searchResault.Repositories[1].RepoName, "library/hello-world", "2nd repo name should be") {
|
||||
t.Error("fail to find repo 'library/hello-world'", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
fmt.Println("repo 'library/hello-world' exit")
|
||||
}
|
||||
|
||||
//t.Log(resault)
|
||||
}
|
||||
|
||||
//case 1: admin login fail, expect repo delete fail.
|
||||
fmt.Println("case 1: admin login fail, expect repo delete fail.")
|
||||
|
||||
resault, err := apiTest.HarborLogin(*adminEr)
|
||||
if err != nil {
|
||||
t.Error("Error while admin login", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
assert.Equal(resault, int(401), "Admin login status should be 401")
|
||||
//t.Log(resault)
|
||||
}
|
||||
if resault != 401 {
|
||||
t.Log(resault)
|
||||
} else {
|
||||
prjUsr = adminEr
|
||||
}
|
||||
|
||||
resault, err = apiTest.RepositoriesDelete(*prjUsr, "library/docker", "")
|
||||
if err != nil {
|
||||
t.Error("Error while delete repository", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
assert.Equal(resault, int(401), "Case 1: Repository delete status should be 401")
|
||||
//t.Log(resault)
|
||||
}
|
||||
|
||||
//case 2: admin successful login, expect repository delete success.
|
||||
fmt.Println("case 2: admin successful login, expect repository delete success.")
|
||||
resault, err = apiTest.HarborLogin(*admin)
|
||||
if err != nil {
|
||||
t.Error("Error while admin login", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
assert.Equal(resault, int(200), "Admin login status should be 200")
|
||||
//t.Log(resault)
|
||||
}
|
||||
if resault != 200 {
|
||||
t.Log(resault)
|
||||
} else {
|
||||
prjUsr = admin
|
||||
}
|
||||
|
||||
resault, err = apiTest.RepositoriesDelete(*prjUsr, "library/docker", "")
|
||||
if err != nil {
|
||||
t.Error("Error while delete repository", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
if assert.Equal(resault, int(200), "Case 2: Repository delete status should be 200") {
|
||||
fmt.Println("Repository 'library/docker' delete success.")
|
||||
}
|
||||
//t.Log(resault)
|
||||
}
|
||||
|
||||
resault, err = apiTest.RepositoriesDelete(*prjUsr, "library/hello-world", "")
|
||||
if err != nil {
|
||||
t.Error("Error while delete repository", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
if assert.Equal(resault, int(200), "Case 2: Repository delete status should be 200") {
|
||||
fmt.Println("Repository 'hello-world' delete success.")
|
||||
}
|
||||
//t.Log(resault)
|
||||
}
|
||||
|
||||
//case 3: delete one repo not exit, expect repo delete fail.
|
||||
fmt.Println("case 3: delete one repo not exit, expect repo delete fail.")
|
||||
|
||||
resault, err = apiTest.RepositoriesDelete(*prjUsr, "library/hello-world", "")
|
||||
if err != nil {
|
||||
t.Error("Error while delete repository", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
if assert.Equal(resault, int(404), "Case 3: Repository delete status should be 404") {
|
||||
fmt.Println("Repository 'hello-world' not exit.")
|
||||
}
|
||||
//t.Log(resault)
|
||||
}
|
||||
|
||||
//if resault.Response.StatusCode != 200 {
|
||||
// t.Log(resault.Response)
|
||||
//}
|
||||
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package HarborAPItest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
"github.com/vmware/harbor/tests/apitests/apilib"
|
||||
)
|
||||
|
||||
func TestSearch(t *testing.T) {
|
||||
fmt.Println("Test for Search (SearchGet) API")
|
||||
assert := assert.New(t)
|
||||
|
||||
apiTest := HarborAPI.NewHarborAPI()
|
||||
var resault HarborAPI.Search
|
||||
resault, err := apiTest.SearchGet("library")
|
||||
//fmt.Printf("%+v\n", resault)
|
||||
if err != nil {
|
||||
t.Error("Error while search project or repository", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
assert.Equal(resault.Projects[0].ProjectId, int32(1), "Project id should be equal")
|
||||
assert.Equal(resault.Projects[0].ProjectName, "library", "Project name should be library")
|
||||
assert.Equal(resault.Projects[0].Public, int32(1), "Project public status should be 1 (true)")
|
||||
//t.Log(resault)
|
||||
}
|
||||
//if resault.Response.StatusCode != 200 {
|
||||
// t.Log(resault.Response)
|
||||
//}
|
||||
|
||||
}
|
23
tests/docker-compose.test.yml
Normal file
23
tests/docker-compose.test.yml
Normal file
@ -0,0 +1,23 @@
|
||||
version: '2'
|
||||
services:
|
||||
registry:
|
||||
image: library/registry:2.4.0
|
||||
restart: always
|
||||
volumes:
|
||||
- /data/registry:/storage
|
||||
- ./config/registry/:/etc/registry/
|
||||
environment:
|
||||
- GODEBUG=netdns=cgo
|
||||
ports:
|
||||
- 5000:5000
|
||||
command:
|
||||
["serve", "/etc/registry/config.yml"]
|
||||
mysql:
|
||||
build: ./db/
|
||||
restart: always
|
||||
volumes:
|
||||
- /data/database:/var/lib/mysql
|
||||
env_file:
|
||||
- ./config/db/env
|
||||
ports:
|
||||
- 3306:3306
|
@ -1,10 +1,9 @@
|
||||
docker pull hello-world
|
||||
docker pull docker
|
||||
docker login -u admin -p Harbor12345 127.0.0.1
|
||||
#!/bin/bash
|
||||
|
||||
docker tag hello-world 127.0.0.1/library/hello-world
|
||||
docker push 127.0.0.1/library/hello-world
|
||||
cp tests/docker-compose.test.yml Deploy/.
|
||||
|
||||
docker tag docker 127.0.0.1/library/docker
|
||||
docker push 127.0.0.1/library/docker
|
||||
mkdir /etc/ui
|
||||
cp Deploy/config/ui/private_key.pem /etc/ui/.
|
||||
|
||||
mkdir conf
|
||||
cp Deploy/config/ui/app.conf conf/.
|
||||
|
Loading…
Reference in New Issue
Block a user