harbor/src/ui/api/project_test.go
Steven Zou b501199033 Enhance the project deletable checking logic to include helm charts checking
add utility handler in chart controller to support getting charts by ns
add ut case for utility handler
update deletable checking logic in project controller

refactor project deletable test case
2018-08-06 15:23:50 +08:00

445 lines
14 KiB
Go

// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
//
// 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 api
import (
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"strconv"
"testing"
"time"
"github.com/vmware/harbor/src/chartserver"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/vmware/harbor/src/common/dao"
"github.com/vmware/harbor/src/common/models"
"github.com/vmware/harbor/tests/apitests/apilib"
)
var addProject *apilib.ProjectReq
var addPID int
func InitAddPro() {
addProject = &apilib.ProjectReq{"add_project", map[string]string{models.ProMetaPublic: "true"}}
}
func TestAddProject(t *testing.T) {
fmt.Println("\nTesting Add Project(ProjectsPost) API")
assert := assert.New(t)
apiTest := newHarborAPI()
//prepare for test
InitAddPro()
//case 1: admin not login, expect project creation fail.
result, err := apiTest.ProjectsPost(*unknownUsr, *addProject)
if err != nil {
t.Error("Error while creat project", err.Error())
t.Log(err)
} else {
assert.Equal(int(401), result, "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.")
result, err = apiTest.ProjectsPost(*admin, *addProject)
if err != nil {
t.Error("Error while creat project", err.Error())
t.Log(err)
} else {
assert.Equal(int(201), result, "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(*admin, *addProject)
if err != nil {
t.Error("Error while creat project", err.Error())
t.Log(err)
} else {
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", map[string]string{models.ProMetaPublic: "true"}})
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 TestListProjects(t *testing.T) {
fmt.Println("\nTest for Project GET API by project name")
assert := assert.New(t)
apiTest := newHarborAPI()
var result []apilib.Project
//----------------------------case 1 : Response Code=200----------------------------//
fmt.Println("case 1: respose code:200")
httpStatusCode, result, err := apiTest.ProjectsGet(
&apilib.ProjectQuery{
Name: addProject.ProjectName,
Owner: admin.Name,
Public: true,
})
assert.Nil(err)
assert.Equal(int(200), httpStatusCode, "httpStatusCode should be 200")
assert.Equal(addProject.ProjectName, result[0].ProjectName, "Project name is wrong")
assert.Equal("true", result[0].Metadata[models.ProMetaPublic], "Public is wrong")
//find add projectID
addPID = int(result[0].ProjectId)
//-------------------case 3 : check admin project role------------------------//
httpStatusCode, result, err = apiTest.ProjectsGet(
&apilib.ProjectQuery{
Name: addProject.ProjectName,
Owner: admin.Name,
Public: true,
}, *admin)
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")
assert.Equal(addProject.ProjectName, result[0].ProjectName, "Project name is wrong")
assert.Equal("true", result[0].Metadata[models.ProMetaPublic], "Public is wrong")
assert.Equal(int32(1), result[0].CurrentUserRoleId, "User project role is wrong")
}
//-------------------case 4 : add project member and check his role ------------------------//
CommonAddUser()
member := &models.MemberReq{
Role: 2,
MemberUser: models.User{
Username: TestUserName,
},
}
projectID := strconv.Itoa(addPID)
httpStatusCode, err = apiTest.AddProjectMember(*admin, projectID, member)
if err != nil {
t.Error("Error whihle add project role member", err.Error())
t.Log(err)
} else {
assert.Equal(int(201), httpStatusCode, "httpStatusCode should be 201")
}
httpStatusCode, result, err = apiTest.ProjectsGet(
&apilib.ProjectQuery{
Name: addProject.ProjectName,
}, *testUser)
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")
assert.Equal(addProject.ProjectName, result[0].ProjectName, "Project name is wrong")
assert.Equal("true", result[0].Metadata[models.ProMetaPublic], "Public is wrong")
assert.Equal(int32(2), result[0].CurrentUserRoleId, "User project role is wrong")
}
id := strconv.Itoa(CommonGetUserID())
httpStatusCode, err = apiTest.DeleteProjectMember(*admin, projectID, id)
if err != nil {
t.Error("Error whihle add project role member", err.Error())
t.Log(err)
} else {
assert.Equal(int(200), httpStatusCode, "httpStatusCode should be 200")
}
CommonDelUser()
}
//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("true", result.Metadata[models.ProMetaPublic], "Public is wrong")
}
fmt.Printf("\n")
}
func TestDeleteProject(t *testing.T) {
fmt.Println("\nTesting Delete Project(ProjectsPost) API")
assert := assert.New(t)
apiTest := newHarborAPI()
projectID := strconv.Itoa(addPID)
//--------------------------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(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) {
fmt.Println("\nTest for Project HEAD API")
assert := assert.New(t)
apiTest := newHarborAPI()
//----------------------------case 1 : Response Code=200----------------------------//
fmt.Println("case 1: respose code:200")
httpStatusCode, err := apiTest.ProjectsHead(*admin, "library")
if err != nil {
t.Error("Error while search project by proName", err.Error())
t.Log(err)
} else {
assert.Equal(int(200), httpStatusCode, "httpStatusCode should be 200")
}
//----------------------------case 2 : Response Code=404:Project name does not exist.----------------------------//
fmt.Println("case 2: respose code:404,Project name does not exist.")
httpStatusCode, err = apiTest.ProjectsHead(*admin, "libra")
if err != nil {
t.Error("Error while search project by proName", err.Error())
t.Log(err)
} else {
assert.Equal(int(404), httpStatusCode, "httpStatusCode should be 404")
}
fmt.Printf("\n")
}
func TestPut(t *testing.T) {
fmt.Println("\nTest for Project PUT API: Update properties for a selected project")
assert := assert.New(t)
apiTest := newHarborAPI()
project := &models.Project{
Metadata: map[string]string{
models.ProMetaPublic: "true",
},
}
fmt.Println("case 1: respose code:200")
code, err := apiTest.ProjectsPut(*admin, "1", project)
require.Nil(t, err)
assert.Equal(int(200), code)
fmt.Println("case 2: respose code:401, User need to log in first.")
code, err = apiTest.ProjectsPut(*unknownUsr, "1", project)
require.Nil(t, err)
assert.Equal(int(401), code)
fmt.Println("case 3: respose code:400, Invalid project id")
code, err = apiTest.ProjectsPut(*admin, "cc", project)
require.Nil(t, err)
assert.Equal(int(400), code)
fmt.Println("case 4: respose code:404, Not found the project")
code, err = apiTest.ProjectsPut(*admin, "1234", project)
require.Nil(t, err)
assert.Equal(int(404), code)
fmt.Printf("\n")
}
func TestProjectLogsFilter(t *testing.T) {
fmt.Println("\nTest for search access logs filtered by operations and date time ranges..")
assert := assert.New(t)
apiTest := newHarborAPI()
query := &apilib.LogQuery{
Username: "admin",
Repository: "",
Tag: "",
Operation: []string{""},
BeginTimestamp: 0,
EndTimestamp: time.Now().Unix(),
}
//-------------------case1: Response Code=200------------------------------//
fmt.Println("case 1: respose code:200")
projectID := "1"
httpStatusCode, _, err := apiTest.ProjectLogs(*admin, projectID, query)
if err != nil {
t.Error("Error while search access logs")
t.Log(err)
} else {
assert.Equal(int(200), httpStatusCode, "httpStatusCode should be 200")
}
//-------------------case2: Response Code=401:User need to log in first.------------------------------//
fmt.Println("case 2: respose code:401:User need to log in first.")
projectID = "1"
httpStatusCode, _, err = apiTest.ProjectLogs(*unknownUsr, projectID, query)
if err != nil {
t.Error("Error while search access logs")
t.Log(err)
} else {
assert.Equal(int(401), httpStatusCode, "httpStatusCode should be 401")
}
//-------------------case3: Response Code=404:Project does not exist.-------------------------//
fmt.Println("case 3: respose code:404:Illegal format of provided ID value.")
projectID = "11111"
httpStatusCode, _, err = apiTest.ProjectLogs(*admin, projectID, query)
if err != nil {
t.Error("Error while search access logs")
t.Log(err)
} else {
assert.Equal(int(404), httpStatusCode, "httpStatusCode should be 404")
}
fmt.Printf("\n")
}
func TestDeletable(t *testing.T) {
apiTest := newHarborAPI()
chServer, oldController, err := mockChartController()
require.Nil(t, err)
require.NotNil(t, chServer)
defer chServer.Close()
defer func() {
chartController = oldController
}()
project := models.Project{
Name: "project_for_test_deletable",
OwnerID: 1,
}
id, err := dao.AddProject(project)
require.Nil(t, err)
// non-exist project
code, del, err := apiTest.ProjectDeletable(*admin, 1000)
assert.Nil(t, err)
assert.Equal(t, http.StatusNotFound, code)
// unauthorized
code, del, err = apiTest.ProjectDeletable(*unknownUsr, id)
assert.Nil(t, err)
assert.Equal(t, http.StatusUnauthorized, code)
// can be deleted
code, del, err = apiTest.ProjectDeletable(*admin, id)
assert.Nil(t, err)
assert.Equal(t, http.StatusOK, code)
assert.True(t, del)
err = dao.AddRepository(models.RepoRecord{
Name: project.Name + "/golang",
ProjectID: id,
})
require.Nil(t, err)
// can not be deleted as contains repository
code, del, err = apiTest.ProjectDeletable(*admin, id)
assert.Nil(t, err)
assert.Equal(t, http.StatusOK, code)
assert.False(t, del)
}
//Provides a mock chart controller for deletable test cases
func mockChartController() (*httptest.Server, *chartserver.Controller, error) {
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.RequestURI {
case "/api/project_for_test_deletable/charts":
if r.Method == http.MethodGet {
w.Write([]byte("{}"))
return
}
}
w.WriteHeader(http.StatusNotImplemented)
w.Write([]byte("not supported"))
}))
var oldController, newController *chartserver.Controller
url, err := url.Parse(mockServer.URL)
if err == nil {
newController, err = chartserver.NewController(url)
}
if err != nil {
mockServer.Close()
return nil, nil, err
}
//Override current controller and keep the old one for restoring
oldController = chartController
chartController = newController
return mockServer, oldController, nil
}