mirror of
https://github.com/goharbor/harbor
synced 2024-09-20 21:34:15 +00:00
Merge pull request #2495 from ywk253100/170605_pm
Implement project manager based on PMS
This commit is contained in:
commit
f0c47b990b
|
@ -91,6 +91,7 @@ script:
|
||||||
- ./tests/pushimage.sh
|
- ./tests/pushimage.sh
|
||||||
- cd tests
|
- cd tests
|
||||||
- sudo ./ldapprepare.sh
|
- sudo ./ldapprepare.sh
|
||||||
|
- sudo ./admiral.sh
|
||||||
- cd ..
|
- cd ..
|
||||||
- go test -i ./src/ui ./src/adminserver ./src/jobservice
|
- go test -i ./src/ui ./src/adminserver ./src/jobservice
|
||||||
- sudo -E env "PATH=$PATH" ./tests/coverage4gotest.sh
|
- sudo -E env "PATH=$PATH" ./tests/coverage4gotest.sh
|
||||||
|
|
|
@ -28,9 +28,6 @@ const (
|
||||||
RoleDeveloper = 2
|
RoleDeveloper = 2
|
||||||
RoleGuest = 3
|
RoleGuest = 3
|
||||||
|
|
||||||
DeployModeStandAlone = "standalone"
|
|
||||||
DeployModeIntegration = "integration"
|
|
||||||
|
|
||||||
ExtEndpoint = "ext_endpoint"
|
ExtEndpoint = "ext_endpoint"
|
||||||
AUTHMode = "auth_mode"
|
AUTHMode = "auth_mode"
|
||||||
DatabaseType = "database_type"
|
DatabaseType = "database_type"
|
||||||
|
|
|
@ -31,11 +31,14 @@ type Project struct {
|
||||||
OwnerName string `orm:"-" json:"owner_name"`
|
OwnerName string `orm:"-" json:"owner_name"`
|
||||||
Public int `orm:"column(public)" json:"public"`
|
Public int `orm:"column(public)" json:"public"`
|
||||||
//This field does not have correspondent column in DB, this is just for UI to disable button
|
//This field does not have correspondent column in DB, this is just for UI to disable button
|
||||||
Togglable bool `orm:"-"`
|
Togglable bool `orm:"-"`
|
||||||
|
UpdateTime time.Time `orm:"update_time" json:"update_time"`
|
||||||
UpdateTime time.Time `orm:"update_time" json:"update_time"`
|
Role int `orm:"-" json:"current_user_role_id"`
|
||||||
Role int `orm:"-" json:"current_user_role_id"`
|
RepoCount int `orm:"-" json:"repo_count"`
|
||||||
RepoCount int `orm:"-" json:"repo_count"`
|
EnableContentTrust bool `orm:"-" json:"enable_content_trust"`
|
||||||
|
PreventVulnerableImagesFromRunning bool `orm:"-" json:"prevent_vulnerable_images_from_running"`
|
||||||
|
PreventVulnerableImagesFromRunningSeverity string `orm:"-" json:"prevent_vulnerable_images_from_running_severity"`
|
||||||
|
AutomaticallyScanImagesOnPush bool `orm:"-" json:"automatically_scan_images_on_push"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProjectSorter holds an array of projects
|
// ProjectSorter holds an array of projects
|
||||||
|
|
|
@ -27,7 +27,7 @@ import (
|
||||||
//"github.com/vmware/harbor/src/common/config"
|
//"github.com/vmware/harbor/src/common/config"
|
||||||
"github.com/vmware/harbor/src/common/utils/log"
|
"github.com/vmware/harbor/src/common/utils/log"
|
||||||
"github.com/vmware/harbor/src/common/utils/registry"
|
"github.com/vmware/harbor/src/common/utils/registry"
|
||||||
registry_error "github.com/vmware/harbor/src/common/utils/registry/error"
|
registry_error "github.com/vmware/harbor/src/common/utils/error"
|
||||||
token_util "github.com/vmware/harbor/src/ui/service/token"
|
token_util "github.com/vmware/harbor/src/ui/service/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ import (
|
||||||
// "time"
|
// "time"
|
||||||
|
|
||||||
"github.com/vmware/harbor/src/common/utils"
|
"github.com/vmware/harbor/src/common/utils"
|
||||||
registry_error "github.com/vmware/harbor/src/common/utils/registry/error"
|
registry_error "github.com/vmware/harbor/src/common/utils/error"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Registry holds information of a registry entity
|
// Registry holds information of a registry entity
|
||||||
|
|
|
@ -30,7 +30,7 @@ import (
|
||||||
"github.com/docker/distribution/manifest/schema2"
|
"github.com/docker/distribution/manifest/schema2"
|
||||||
|
|
||||||
"github.com/vmware/harbor/src/common/utils"
|
"github.com/vmware/harbor/src/common/utils"
|
||||||
registry_error "github.com/vmware/harbor/src/common/utils/registry/error"
|
registry_error "github.com/vmware/harbor/src/common/utils/error"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Repository holds information of a repository entity
|
// Repository holds information of a repository entity
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/distribution/manifest/schema2"
|
"github.com/docker/distribution/manifest/schema2"
|
||||||
registry_error "github.com/vmware/harbor/src/common/utils/registry/error"
|
registry_error "github.com/vmware/harbor/src/common/utils/error"
|
||||||
"github.com/vmware/harbor/src/common/utils/test"
|
"github.com/vmware/harbor/src/common/utils/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ import (
|
||||||
"github.com/vmware/harbor/src/common/utils/log"
|
"github.com/vmware/harbor/src/common/utils/log"
|
||||||
"github.com/vmware/harbor/src/common/utils/notary"
|
"github.com/vmware/harbor/src/common/utils/notary"
|
||||||
"github.com/vmware/harbor/src/common/utils/registry"
|
"github.com/vmware/harbor/src/common/utils/registry"
|
||||||
registry_error "github.com/vmware/harbor/src/common/utils/registry/error"
|
registry_error "github.com/vmware/harbor/src/common/utils/error"
|
||||||
"github.com/vmware/harbor/src/ui/config"
|
"github.com/vmware/harbor/src/ui/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ import (
|
||||||
"github.com/vmware/harbor/src/common/utils/log"
|
"github.com/vmware/harbor/src/common/utils/log"
|
||||||
"github.com/vmware/harbor/src/common/utils/registry"
|
"github.com/vmware/harbor/src/common/utils/registry"
|
||||||
"github.com/vmware/harbor/src/common/utils/registry/auth"
|
"github.com/vmware/harbor/src/common/utils/registry/auth"
|
||||||
registry_error "github.com/vmware/harbor/src/common/utils/registry/error"
|
registry_error "github.com/vmware/harbor/src/common/utils/error"
|
||||||
"github.com/vmware/harbor/src/ui/config"
|
"github.com/vmware/harbor/src/ui/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ import (
|
||||||
"github.com/vmware/harbor/src/common/utils/log"
|
"github.com/vmware/harbor/src/common/utils/log"
|
||||||
"github.com/vmware/harbor/src/common/utils/registry"
|
"github.com/vmware/harbor/src/common/utils/registry"
|
||||||
"github.com/vmware/harbor/src/common/utils/registry/auth"
|
"github.com/vmware/harbor/src/common/utils/registry/auth"
|
||||||
registry_error "github.com/vmware/harbor/src/common/utils/registry/error"
|
registry_error "github.com/vmware/harbor/src/common/utils/error"
|
||||||
"github.com/vmware/harbor/src/ui/config"
|
"github.com/vmware/harbor/src/ui/config"
|
||||||
"github.com/vmware/harbor/src/ui/projectmanager"
|
"github.com/vmware/harbor/src/ui/projectmanager"
|
||||||
)
|
)
|
||||||
|
|
|
@ -95,8 +95,7 @@ func initSecretStore() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func initProjectManager() {
|
func initProjectManager() {
|
||||||
if len(DeployMode()) == 0 ||
|
if !WithAdmiral() {
|
||||||
DeployMode() == common.DeployModeStandAlone {
|
|
||||||
log.Info("initializing the project manager based on database...")
|
log.Info("initializing the project manager based on database...")
|
||||||
GlobalProjectMgr = &db.ProjectManager{}
|
GlobalProjectMgr = &db.ProjectManager{}
|
||||||
}
|
}
|
||||||
|
@ -332,9 +331,3 @@ func AdmiralEndpoint() string {
|
||||||
func WithAdmiral() bool {
|
func WithAdmiral() bool {
|
||||||
return len(AdmiralEndpoint()) > 0
|
return len(AdmiralEndpoint()) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeployMode returns the deploy mode
|
|
||||||
// TODO read from adminserver
|
|
||||||
func DeployMode() string {
|
|
||||||
return common.DeployModeStandAlone
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
beegoctx "github.com/astaxie/beego/context"
|
beegoctx "github.com/astaxie/beego/context"
|
||||||
"github.com/vmware/harbor/src/common"
|
|
||||||
"github.com/vmware/harbor/src/common/models"
|
"github.com/vmware/harbor/src/common/models"
|
||||||
"github.com/vmware/harbor/src/common/security"
|
"github.com/vmware/harbor/src/common/security"
|
||||||
"github.com/vmware/harbor/src/common/security/rbac"
|
"github.com/vmware/harbor/src/common/security/rbac"
|
||||||
|
@ -30,6 +29,7 @@ import (
|
||||||
"github.com/vmware/harbor/src/ui/auth"
|
"github.com/vmware/harbor/src/ui/auth"
|
||||||
"github.com/vmware/harbor/src/ui/config"
|
"github.com/vmware/harbor/src/ui/config"
|
||||||
"github.com/vmware/harbor/src/ui/projectmanager"
|
"github.com/vmware/harbor/src/ui/projectmanager"
|
||||||
|
"github.com/vmware/harbor/src/ui/projectmanager/pms"
|
||||||
)
|
)
|
||||||
|
|
||||||
type key string
|
type key string
|
||||||
|
@ -133,15 +133,14 @@ func fillContext(ctx *beegoctx.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getProjectManager(ctx *beegoctx.Context) projectmanager.ProjectManager {
|
func getProjectManager(ctx *beegoctx.Context) projectmanager.ProjectManager {
|
||||||
if len(config.DeployMode()) == 0 ||
|
if !config.WithAdmiral() {
|
||||||
config.DeployMode() == common.DeployModeStandAlone {
|
|
||||||
log.Info("filling a project manager based on database...")
|
log.Info("filling a project manager based on database...")
|
||||||
return config.GlobalProjectMgr
|
return config.GlobalProjectMgr
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO create project manager based on pms
|
log.Info("filling a project manager based on PMS...")
|
||||||
log.Info("filling a project manager based on pms...")
|
// TODO pass the token to the function
|
||||||
return nil
|
return pms.NewProjectManager(config.AdmiralEndpoint(), "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSecurityContext tries to get security context from request and returns it
|
// GetSecurityContext tries to get security context from request and returns it
|
||||||
|
|
422
src/ui/projectmanager/pms/pm.go
Normal file
422
src/ui/projectmanager/pms/pm.go
Normal file
|
@ -0,0 +1,422 @@
|
||||||
|
// 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 pms
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/vmware/harbor/src/common"
|
||||||
|
"github.com/vmware/harbor/src/common/models"
|
||||||
|
er "github.com/vmware/harbor/src/common/utils/error"
|
||||||
|
"github.com/vmware/harbor/src/common/utils/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
var transport = &http.Transport{}
|
||||||
|
|
||||||
|
// ProjectManager implements projectmanager.ProjecdtManager interface
|
||||||
|
// base on project management service
|
||||||
|
type ProjectManager struct {
|
||||||
|
endpoint string
|
||||||
|
token string
|
||||||
|
client *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
type user struct {
|
||||||
|
Email string `json:"email"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type project struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Public bool `json:"isPublic"`
|
||||||
|
OwnerID string `json:"documentOwner"`
|
||||||
|
CustomProperties map[string]string `json:"customProperties"`
|
||||||
|
Administrators []*user `json:"administrators"`
|
||||||
|
Developers []*user `json:"members"`
|
||||||
|
Guests []*user `json:"guests"` // TODO the json name needs to be modified according to the API
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewProjectManager returns an instance of ProjectManager
|
||||||
|
func NewProjectManager(endpoint, token string) *ProjectManager {
|
||||||
|
return &ProjectManager{
|
||||||
|
endpoint: strings.TrimRight(endpoint, "/"),
|
||||||
|
token: token,
|
||||||
|
client: &http.Client{
|
||||||
|
Transport: transport,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get ...
|
||||||
|
func (p *ProjectManager) Get(projectIDOrName interface{}) (*models.Project, error) {
|
||||||
|
project, err := p.get(projectIDOrName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return convert(project)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ProjectManager) get(projectIDOrName interface{}) (*project, error) {
|
||||||
|
m := map[string]string{}
|
||||||
|
if id, ok := projectIDOrName.(int64); ok {
|
||||||
|
m["customProperties.__harborId"] = strconv.FormatInt(id, 10)
|
||||||
|
} else if name, ok := projectIDOrName.(string); ok {
|
||||||
|
m["name"] = name
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("unsupported type: %v", projectIDOrName)
|
||||||
|
}
|
||||||
|
|
||||||
|
projects, err := p.filter(m)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(projects) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(projects) != 1 {
|
||||||
|
return nil, fmt.Errorf("unexpected size of project list: %d != 1", len(projects))
|
||||||
|
}
|
||||||
|
|
||||||
|
return projects[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ProjectManager) filter(m map[string]string) ([]*project, error) {
|
||||||
|
query := ""
|
||||||
|
for k, v := range m {
|
||||||
|
if len(query) == 0 {
|
||||||
|
query += "?"
|
||||||
|
} else {
|
||||||
|
query += "&"
|
||||||
|
}
|
||||||
|
query += fmt.Sprintf("$filter=%s eq '%s'", k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
path := "/projects" + query
|
||||||
|
data, err := p.send(http.MethodGet, path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return parse(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse the response of GET /projects?xxx to project list
|
||||||
|
func parse(b []byte) ([]*project, error) {
|
||||||
|
documents := &struct {
|
||||||
|
//TotalCount int64 `json:"totalCount"`
|
||||||
|
//DocumentCount int64 `json:"documentCount"`
|
||||||
|
Projects map[string]*project `json:"documents"`
|
||||||
|
}{}
|
||||||
|
if err := json.Unmarshal(b, documents); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
projects := []*project{}
|
||||||
|
for link, project := range documents.Projects {
|
||||||
|
project.ID = strings.TrimLeft(link, "/projects/")
|
||||||
|
projects = append(projects, project)
|
||||||
|
}
|
||||||
|
|
||||||
|
return projects, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func convert(p *project) (*models.Project, error) {
|
||||||
|
if p == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
project := &models.Project{
|
||||||
|
Name: p.Name,
|
||||||
|
}
|
||||||
|
if p.Public {
|
||||||
|
project.Public = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
value := p.CustomProperties["__harborId"]
|
||||||
|
if len(value) == 0 {
|
||||||
|
return nil, fmt.Errorf("property __harborId is null")
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := strconv.ParseInt(value, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse __harborId %s to int64: %v", value, err)
|
||||||
|
}
|
||||||
|
project.ProjectID = id
|
||||||
|
|
||||||
|
value = p.CustomProperties["__enableContentTrust"]
|
||||||
|
if len(value) != 0 {
|
||||||
|
enable, err := strconv.ParseBool(value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse __enableContentTrust %s to bool: %v", value, err)
|
||||||
|
}
|
||||||
|
project.EnableContentTrust = enable
|
||||||
|
}
|
||||||
|
|
||||||
|
value = p.CustomProperties["__preventVulnerableImagesFromRunning"]
|
||||||
|
if len(value) != 0 {
|
||||||
|
prevent, err := strconv.ParseBool(value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse __preventVulnerableImagesFromRunning %s to bool: %v", value, err)
|
||||||
|
}
|
||||||
|
project.PreventVulnerableImagesFromRunning = prevent
|
||||||
|
}
|
||||||
|
|
||||||
|
value = p.CustomProperties["__preventVulnerableImagesFromRunningSeverity"]
|
||||||
|
if len(value) != 0 {
|
||||||
|
project.PreventVulnerableImagesFromRunningSeverity = value
|
||||||
|
}
|
||||||
|
|
||||||
|
value = p.CustomProperties["__automaticallyScanImagesOnPush"]
|
||||||
|
if len(value) != 0 {
|
||||||
|
scan, err := strconv.ParseBool(value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse __automaticallyScanImagesOnPush %s to bool: %v", value, err)
|
||||||
|
}
|
||||||
|
project.AutomaticallyScanImagesOnPush = scan
|
||||||
|
}
|
||||||
|
|
||||||
|
return project, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPublic ...
|
||||||
|
func (p *ProjectManager) IsPublic(projectIDOrName interface{}) (bool, error) {
|
||||||
|
project, err := p.get(projectIDOrName)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if project == nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return project.Public, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exist ...
|
||||||
|
func (p *ProjectManager) Exist(projectIDOrName interface{}) (bool, error) {
|
||||||
|
project, err := p.get(projectIDOrName)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return project != nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRoles ...
|
||||||
|
// TODO empty this method after implementing security context with auth context
|
||||||
|
func (p *ProjectManager) GetRoles(username string, projectIDOrName interface{}) ([]int, error) {
|
||||||
|
if len(username) == 0 || projectIDOrName == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := p.getIDbyHarborIDOrName(projectIDOrName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// get expanded project which contains role info by GET /projects/id?expand=true
|
||||||
|
path := fmt.Sprintf("/projects/%s?expand=true", id)
|
||||||
|
data, err := p.send(http.MethodGet, path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pro := &project{}
|
||||||
|
if err = json.Unmarshal(data, pro); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
roles := []int{}
|
||||||
|
|
||||||
|
for _, user := range pro.Administrators {
|
||||||
|
if user.Email == username {
|
||||||
|
roles = append(roles, common.RoleProjectAdmin)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, user := range pro.Developers {
|
||||||
|
if user.Email == username {
|
||||||
|
roles = append(roles, common.RoleDeveloper)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, user := range pro.Guests {
|
||||||
|
if user.Email == username {
|
||||||
|
roles = append(roles, common.RoleGuest)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return roles, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ProjectManager) getIDbyHarborIDOrName(projectIDOrName interface{}) (string, error) {
|
||||||
|
pro, err := p.get(projectIDOrName)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if pro == nil {
|
||||||
|
return "", fmt.Errorf("project %v not found", projectIDOrName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pro.ID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPublic ...
|
||||||
|
func (p *ProjectManager) GetPublic() ([]*models.Project, error) {
|
||||||
|
m := map[string]string{
|
||||||
|
"isPublic": "true",
|
||||||
|
}
|
||||||
|
|
||||||
|
projects, err := p.filter(m)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
list := []*models.Project{}
|
||||||
|
for _, p := range projects {
|
||||||
|
project, err := convert(p)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
list = append(list, project)
|
||||||
|
}
|
||||||
|
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByMember ...
|
||||||
|
func (p *ProjectManager) GetByMember(username string) ([]*models.Project, error) {
|
||||||
|
// TODO add implement
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create ...
|
||||||
|
func (p *ProjectManager) Create(pro *models.Project) (int64, error) {
|
||||||
|
proj := &project{
|
||||||
|
CustomProperties: make(map[string]string),
|
||||||
|
}
|
||||||
|
proj.Name = pro.Name
|
||||||
|
proj.Public = pro.Public == 1
|
||||||
|
proj.CustomProperties["__enableContentTrust"] = strconv.FormatBool(pro.EnableContentTrust)
|
||||||
|
proj.CustomProperties["__preventVulnerableImagesFromRunning"] = strconv.FormatBool(pro.PreventVulnerableImagesFromRunning)
|
||||||
|
proj.CustomProperties["__preventVulnerableImagesFromRunningSeverity"] = pro.PreventVulnerableImagesFromRunningSeverity
|
||||||
|
proj.CustomProperties["__automaticallyScanImagesOnPush"] = strconv.FormatBool(pro.AutomaticallyScanImagesOnPush)
|
||||||
|
|
||||||
|
// TODO remove the logic if Admiral generates the harborId
|
||||||
|
proj.CustomProperties["__harborId"] = strconv.FormatInt(time.Now().UnixNano(), 10)
|
||||||
|
|
||||||
|
data, err := json.Marshal(proj)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := p.send(http.MethodPost, "/projects", bytes.NewBuffer(data))
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
proj = &project{}
|
||||||
|
if err = json.Unmarshal(b, proj); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pp, err := convert(proj)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pp.ProjectID, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete ...
|
||||||
|
func (p *ProjectManager) Delete(projectIDOrName interface{}) error {
|
||||||
|
id, err := p.getIDbyHarborIDOrName(projectIDOrName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = p.send(http.MethodDelete, fmt.Sprintf("/projects/%s", id), nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update ...
|
||||||
|
func (p *ProjectManager) Update(projectIDOrName interface{}, project *models.Project) error {
|
||||||
|
return errors.New("project update is unsupported")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAll ...
|
||||||
|
func (p *ProjectManager) GetAll(query *models.ProjectQueryParam) ([]*models.Project, error) {
|
||||||
|
return nil, errors.New("get all projects is unsupported")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTotal ...
|
||||||
|
func (p *ProjectManager) GetTotal(query *models.ProjectQueryParam) (int64, error) {
|
||||||
|
return 0, errors.New("get total of projects is unsupported")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetHasReadPerm returns all projects that user has read perm to
|
||||||
|
// TODO maybe can be removed as search isn't implemented in integration mode
|
||||||
|
func (p *ProjectManager) GetHasReadPerm(username ...string) ([]*models.Project, error) {
|
||||||
|
// TODO add implement
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ProjectManager) send(method, path string, body io.Reader) ([]byte, error) {
|
||||||
|
req, err := http.NewRequest(method, p.endpoint+path, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Add("x-xenon-auth-token", p.token)
|
||||||
|
|
||||||
|
url := req.URL.String()
|
||||||
|
|
||||||
|
req.URL.RawQuery = req.URL.Query().Encode()
|
||||||
|
resp, err := p.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
log.Debugf("\"%s %s\" failed", req.Method, url)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
log.Debugf("\"%s %s\" %d", req.Method, url, resp.StatusCode)
|
||||||
|
|
||||||
|
b, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return nil, &er.Error{
|
||||||
|
StatusCode: resp.StatusCode,
|
||||||
|
Detail: string(b),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return b, nil
|
||||||
|
}
|
424
src/ui/projectmanager/pms/pm_test.go
Normal file
424
src/ui/projectmanager/pms/pm_test.go
Normal file
|
@ -0,0 +1,424 @@
|
||||||
|
// 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 pms
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/vmware/harbor/src/common/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
endpoint = "http://127.0.0.1:8282"
|
||||||
|
token = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConvert(t *testing.T) {
|
||||||
|
//nil project
|
||||||
|
pro, err := convert(nil)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Nil(t, pro)
|
||||||
|
|
||||||
|
//project without property __harborId
|
||||||
|
p := &project{}
|
||||||
|
pro, err = convert(p)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
assert.Nil(t, pro)
|
||||||
|
|
||||||
|
//project with invalid __harborId
|
||||||
|
p = &project{
|
||||||
|
CustomProperties: map[string]string{
|
||||||
|
"__harborId": "invalid_value",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
pro, err = convert(p)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
assert.Nil(t, pro)
|
||||||
|
|
||||||
|
//project with invalid __enableContentTrust
|
||||||
|
p = &project{
|
||||||
|
CustomProperties: map[string]string{
|
||||||
|
"__enableContentTrust": "invalid_value",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
pro, err = convert(p)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
assert.Nil(t, pro)
|
||||||
|
|
||||||
|
//project with invalid __preventVulnerableImagesFromRunning
|
||||||
|
p = &project{
|
||||||
|
CustomProperties: map[string]string{
|
||||||
|
"__preventVulnerableImagesFromRunning": "invalid_value",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
pro, err = convert(p)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
assert.Nil(t, pro)
|
||||||
|
|
||||||
|
//project with invalid __automaticallyScanImagesOnPush
|
||||||
|
p = &project{
|
||||||
|
CustomProperties: map[string]string{
|
||||||
|
"__automaticallyScanImagesOnPush": "invalid_value",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
pro, err = convert(p)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
assert.Nil(t, pro)
|
||||||
|
|
||||||
|
//valid project
|
||||||
|
p = &project{
|
||||||
|
Name: "test",
|
||||||
|
Public: true,
|
||||||
|
CustomProperties: map[string]string{
|
||||||
|
"__harborId": "1",
|
||||||
|
"__enableContentTrust": "true",
|
||||||
|
"__preventVulnerableImagesFromRunning": "true",
|
||||||
|
"__preventVulnerableImagesFromRunningSeverity": "medium",
|
||||||
|
"__automaticallyScanImagesOnPush": "true",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
pro, err = convert(p)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, pro)
|
||||||
|
assert.Equal(t, "test", pro.Name)
|
||||||
|
assert.Equal(t, 1, pro.Public)
|
||||||
|
assert.Equal(t, int64(1), pro.ProjectID)
|
||||||
|
assert.True(t, pro.EnableContentTrust)
|
||||||
|
assert.True(t, pro.PreventVulnerableImagesFromRunning)
|
||||||
|
assert.Equal(t, "medium", pro.PreventVulnerableImagesFromRunningSeverity)
|
||||||
|
assert.True(t, pro.AutomaticallyScanImagesOnPush)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParse(t *testing.T) {
|
||||||
|
data := `{
|
||||||
|
"totalCount": 2,
|
||||||
|
"documentLinks": [
|
||||||
|
"/projects/default-project",
|
||||||
|
"/projects/fc6c6c7ddd430875551449a65e7c8"
|
||||||
|
],
|
||||||
|
"documents": {
|
||||||
|
"/projects/fc6c6c7ddd430875551449a65e7c8": {
|
||||||
|
"isPublic": false,
|
||||||
|
"description": "This is a test project.",
|
||||||
|
"id": "41427587-70e9-4671-9a9e-b9def0a07bb7",
|
||||||
|
"name": "project02",
|
||||||
|
"customProperties": {
|
||||||
|
"__harborId": "2",
|
||||||
|
"__enableContentTrust": "true",
|
||||||
|
"__preventVulnerableImagesFromRunning": "true",
|
||||||
|
"__preventVulnerableImagesFromRunningSeverity": "medium",
|
||||||
|
"__automaticallyScanImagesOnPush": "false"
|
||||||
|
},
|
||||||
|
"documentVersion": 0,
|
||||||
|
"documentEpoch": 0,
|
||||||
|
"documentKind": "com:vmware:admiral:auth:project:ProjectService:ProjectState",
|
||||||
|
"documentSelfLink": "/projects/fc6c6c7ddd430875551449a65e7c8",
|
||||||
|
"documentUpdateTimeMicros": 1496729973549001,
|
||||||
|
"documentUpdateAction": "POST",
|
||||||
|
"documentExpirationTimeMicros": 0,
|
||||||
|
"documentOwner": "f65900c4-2b6a-4671-8cf7-c17340dd3d39"
|
||||||
|
},
|
||||||
|
"/projects/default-project": {
|
||||||
|
"isPublic": false,
|
||||||
|
"administratorsUserGroupLink": "/core/authz/user-groups/fc6c6c7ddd43087555143835bcaf8",
|
||||||
|
"membersUserGroupLink": "/core/authz/user-groups/fc6c6c7ddd43087555143835bde80",
|
||||||
|
"id": "default-project",
|
||||||
|
"name": "default-project",
|
||||||
|
"customProperties": {
|
||||||
|
"__harborId": "2",
|
||||||
|
"__enableContentTrust": "true",
|
||||||
|
"__preventVulnerableImagesFromRunning": "true",
|
||||||
|
"__preventVulnerableImagesFromRunningSeverity": "medium",
|
||||||
|
"__automaticallyScanImagesOnPush": "false"
|
||||||
|
},
|
||||||
|
"documentVersion": 0,
|
||||||
|
"documentEpoch": 0,
|
||||||
|
"documentKind": "com:vmware:admiral:auth:project:ProjectService:ProjectState",
|
||||||
|
"documentSelfLink": "/projects/default-project",
|
||||||
|
"documentUpdateTimeMicros": 1496725292012001,
|
||||||
|
"documentUpdateAction": "POST",
|
||||||
|
"documentExpirationTimeMicros": 0,
|
||||||
|
"documentOwner": "f65900c4-2b6a-4671-8cf7-c17340dd3d39",
|
||||||
|
"documentAuthPrincipalLink": "/core/authz/system-user"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"documentCount": 2,
|
||||||
|
"queryTimeMicros": 1,
|
||||||
|
"documentVersion": 0,
|
||||||
|
"documentUpdateTimeMicros": 0,
|
||||||
|
"documentExpirationTimeMicros": 0,
|
||||||
|
"documentOwner": "f65900c4-2b6a-4671-8cf7-c17340dd3d39"
|
||||||
|
}`
|
||||||
|
|
||||||
|
projects, err := parse([]byte(data))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, 2, len(projects))
|
||||||
|
|
||||||
|
ids := []string{projects[0].ID, projects[1].ID}
|
||||||
|
sort.Strings(ids)
|
||||||
|
|
||||||
|
assert.Equal(t, "default-project", ids[0])
|
||||||
|
assert.Equal(t, "fc6c6c7ddd430875551449a65e7c8", ids[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGet(t *testing.T) {
|
||||||
|
pm := NewProjectManager(endpoint, token)
|
||||||
|
name := "project_for_pm_based_on_pms"
|
||||||
|
id, err := pm.Create(&models.Project{
|
||||||
|
Name: name,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer pm.Delete(id)
|
||||||
|
|
||||||
|
// get by invalid input type
|
||||||
|
_, err = pm.Get([]string{})
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
|
// get by invalid ID
|
||||||
|
project, err := pm.Get(int64(0))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Nil(t, project)
|
||||||
|
|
||||||
|
// get by invalid name
|
||||||
|
project, err = pm.Get("invalid_name")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Nil(t, project)
|
||||||
|
|
||||||
|
// get by valid ID
|
||||||
|
project, err = pm.Get(id)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, id, project.ProjectID)
|
||||||
|
|
||||||
|
// get by valid name
|
||||||
|
project, err = pm.Get(name)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, id, project.ProjectID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsPublic(t *testing.T) {
|
||||||
|
pm := NewProjectManager(endpoint, token)
|
||||||
|
|
||||||
|
// invalid input type
|
||||||
|
public, err := pm.IsPublic([]string{})
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
assert.False(t, public)
|
||||||
|
|
||||||
|
// non-exist project
|
||||||
|
public, err = pm.IsPublic(int64(0))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.False(t, public)
|
||||||
|
|
||||||
|
// public project
|
||||||
|
name := "project_for_pm_based_on_pms_public"
|
||||||
|
id, err := pm.Create(&models.Project{
|
||||||
|
Name: name,
|
||||||
|
Public: 1,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer pm.Delete(id)
|
||||||
|
|
||||||
|
public, err = pm.IsPublic(id)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.True(t, public)
|
||||||
|
|
||||||
|
public, err = pm.IsPublic(name)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.True(t, public)
|
||||||
|
|
||||||
|
// private project
|
||||||
|
name = "project_for_pm_based_on_pms_private"
|
||||||
|
id, err = pm.Create(&models.Project{
|
||||||
|
Name: name,
|
||||||
|
Public: 0,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer pm.Delete(id)
|
||||||
|
|
||||||
|
public, err = pm.IsPublic(id)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.False(t, public)
|
||||||
|
|
||||||
|
public, err = pm.IsPublic(name)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.False(t, public)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExist(t *testing.T) {
|
||||||
|
pm := NewProjectManager(endpoint, token)
|
||||||
|
|
||||||
|
// invalid input type
|
||||||
|
exist, err := pm.Exist([]string{})
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
assert.False(t, exist)
|
||||||
|
|
||||||
|
// non-exist project
|
||||||
|
exist, err = pm.Exist(int64(0))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.False(t, exist)
|
||||||
|
|
||||||
|
// exist project
|
||||||
|
name := "project_for_pm_based_on_pms"
|
||||||
|
id, err := pm.Create(&models.Project{
|
||||||
|
Name: name,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer pm.Delete(id)
|
||||||
|
|
||||||
|
exist, err = pm.Exist(id)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.True(t, exist)
|
||||||
|
|
||||||
|
exist, err = pm.Exist(name)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.True(t, exist)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetRoles(t *testing.T) {
|
||||||
|
pm := NewProjectManager(endpoint, token)
|
||||||
|
|
||||||
|
// nil username, nil project
|
||||||
|
roles, err := pm.GetRoles("", nil)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Zero(t, len(roles))
|
||||||
|
|
||||||
|
// non-exist project
|
||||||
|
_, err = pm.GetRoles("user01", "non_exist_project")
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
|
// exist project
|
||||||
|
name := "project_for_pm_based_on_pms"
|
||||||
|
id, err := pm.Create(&models.Project{
|
||||||
|
Name: name,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer pm.Delete(id)
|
||||||
|
|
||||||
|
roles, err = pm.GetRoles("user01", id)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Zero(t, len(roles))
|
||||||
|
|
||||||
|
// TODO add test cases for real role of user
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetPublic(t *testing.T) {
|
||||||
|
pm := NewProjectManager(endpoint, token)
|
||||||
|
|
||||||
|
projects, err := pm.GetPublic()
|
||||||
|
assert.Nil(t, nil)
|
||||||
|
size := len(projects)
|
||||||
|
|
||||||
|
name := "project_for_pm_based_on_pms"
|
||||||
|
id, err := pm.Create(&models.Project{
|
||||||
|
Name: name,
|
||||||
|
Public: 1,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer pm.Delete(id)
|
||||||
|
|
||||||
|
projects, err = pm.GetPublic()
|
||||||
|
assert.Nil(t, nil)
|
||||||
|
assert.Equal(t, size+1, len(projects))
|
||||||
|
|
||||||
|
found := false
|
||||||
|
for _, project := range projects {
|
||||||
|
if project.ProjectID == id {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert.True(t, found)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO add test case
|
||||||
|
func TestGetByMember(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreate(t *testing.T) {
|
||||||
|
pm := NewProjectManager(endpoint, token)
|
||||||
|
|
||||||
|
name := "project_for_pm_based_on_pms"
|
||||||
|
id, err := pm.Create(&models.Project{
|
||||||
|
Name: name,
|
||||||
|
Public: 1,
|
||||||
|
EnableContentTrust: true,
|
||||||
|
PreventVulnerableImagesFromRunning: true,
|
||||||
|
PreventVulnerableImagesFromRunningSeverity: "medium",
|
||||||
|
AutomaticallyScanImagesOnPush: true,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer pm.Delete(id)
|
||||||
|
|
||||||
|
project, err := pm.Get(id)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, name, project.Name)
|
||||||
|
assert.Equal(t, 1, project.Public)
|
||||||
|
assert.True(t, project.EnableContentTrust)
|
||||||
|
assert.True(t, project.PreventVulnerableImagesFromRunning)
|
||||||
|
assert.Equal(t, "medium", project.PreventVulnerableImagesFromRunningSeverity)
|
||||||
|
assert.True(t, project.AutomaticallyScanImagesOnPush)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDelete(t *testing.T) {
|
||||||
|
pm := NewProjectManager(endpoint, token)
|
||||||
|
|
||||||
|
// non-exist project
|
||||||
|
err := pm.Delete(int64(0))
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
|
// delete by ID
|
||||||
|
name := "project_for_pm_based_on_pms_id"
|
||||||
|
id, err := pm.Create(&models.Project{
|
||||||
|
Name: name,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
err = pm.Delete(id)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
// delete by name
|
||||||
|
name = "project_for_pm_based_on_pms_name"
|
||||||
|
id, err = pm.Create(&models.Project{
|
||||||
|
Name: name,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
err = pm.Delete(name)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdate(t *testing.T) {
|
||||||
|
pm := NewProjectManager(endpoint, token)
|
||||||
|
err := pm.Update(nil, nil)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetAll(t *testing.T) {
|
||||||
|
pm := NewProjectManager(endpoint, token)
|
||||||
|
_, err := pm.GetAll(nil)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetTotal(t *testing.T) {
|
||||||
|
pm := NewProjectManager(endpoint, token)
|
||||||
|
_, err := pm.GetTotal(nil)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO add test case
|
||||||
|
func TestGetHasReadPerm(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
7
tests/admiral.sh
Executable file
7
tests/admiral.sh
Executable file
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# run admiral for unit test
|
||||||
|
name=admiral
|
||||||
|
port=8282
|
||||||
|
docker rm -f $name 2>/dev/null
|
||||||
|
docker run -d -p $port:8282 --name $name vmware/admiral:dev
|
Loading…
Reference in New Issue
Block a user