mirror of
https://github.com/goharbor/harbor
synced 2025-04-28 20:16:04 +00:00
Add test case exporter
- cache ut - cli ut - project collector ut - system collector ut Signed-off-by: DQ <dengq@vmware.com>
This commit is contained in:
parent
d95f22448c
commit
85bf88c74e
@ -7,6 +7,8 @@ import (
|
||||
|
||||
var c *cache
|
||||
|
||||
const defaultCacheCleanInterval = 10
|
||||
|
||||
type cachedValue struct {
|
||||
Value interface{}
|
||||
Expiration int64
|
||||
@ -77,7 +79,13 @@ func CacheInit(opt *Opt) {
|
||||
RWMutex: &sync.RWMutex{},
|
||||
}
|
||||
go func() {
|
||||
ticker := time.NewTicker(time.Duration(opt.CacheCleanInterval) * time.Second)
|
||||
var cacheCleanInterval int64
|
||||
if opt.CacheCleanInterval > 0 {
|
||||
cacheCleanInterval = opt.CacheCleanInterval
|
||||
} else {
|
||||
cacheCleanInterval = defaultCacheCleanInterval
|
||||
}
|
||||
ticker := time.NewTicker(time.Duration(cacheCleanInterval) * time.Second)
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
|
38
src/pkg/exporter/cache_test.go
Normal file
38
src/pkg/exporter/cache_test.go
Normal file
@ -0,0 +1,38 @@
|
||||
package exporter
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type CacheTestSuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) SetupTest() {
|
||||
CacheInit(&Opt{
|
||||
CacheDuration: 1,
|
||||
})
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestCacheFunction() {
|
||||
// Empty cache should not contain key1
|
||||
_, ok := CacheGet("key1")
|
||||
c.False(ok)
|
||||
// Put keys to CacheGet
|
||||
CachePut("key1", "value1")
|
||||
CachePut("key2", "value2")
|
||||
// Get key1 should return value1
|
||||
v, ok := CacheGet("key1")
|
||||
c.True(ok)
|
||||
c.Equal("value1", v)
|
||||
// Delete key1, it should not exist anymore
|
||||
CacheDelete("key1")
|
||||
_, ok = CacheGet("key1")
|
||||
c.False(ok)
|
||||
// timeout 1 second
|
||||
time.Sleep(2 * time.Second)
|
||||
_, ok = CacheGet("key2")
|
||||
c.False(ok)
|
||||
}
|
@ -1,10 +1,6 @@
|
||||
package exporter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
@ -24,39 +20,6 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
var hbrCli *HarborClient
|
||||
|
||||
// HarborClient is client for request harbor
|
||||
type HarborClient struct {
|
||||
HarborScheme string
|
||||
HarborHost string
|
||||
HarborPort int
|
||||
*http.Client
|
||||
}
|
||||
|
||||
func (hc HarborClient) harborURL(p string) url.URL {
|
||||
return url.URL{
|
||||
Scheme: hc.HarborScheme,
|
||||
Host: fmt.Sprintf("%s:%d", hc.HarborHost, hc.HarborPort),
|
||||
Path: p,
|
||||
}
|
||||
}
|
||||
|
||||
// Get ...
|
||||
func (hc HarborClient) Get(p string) (*http.Response, error) {
|
||||
hbrURL := hc.harborURL(p)
|
||||
res, err := http.Get(hbrURL.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// InitHarborClient initialize the harbor client
|
||||
func InitHarborClient(hc *HarborClient) {
|
||||
hbrCli = hc
|
||||
}
|
||||
|
||||
func newDesc(subsystem, name, help string) *prometheus.Desc {
|
||||
return prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, subsystem, name),
|
||||
|
40
src/pkg/exporter/harbor_cli.go
Normal file
40
src/pkg/exporter/harbor_cli.go
Normal file
@ -0,0 +1,40 @@
|
||||
package exporter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
var hbrCli *HarborClient
|
||||
|
||||
// HarborClient is client for request harbor
|
||||
type HarborClient struct {
|
||||
HarborScheme string
|
||||
HarborHost string
|
||||
HarborPort int
|
||||
*http.Client
|
||||
}
|
||||
|
||||
func (hc HarborClient) harborURL(p string) url.URL {
|
||||
return url.URL{
|
||||
Scheme: hc.HarborScheme,
|
||||
Host: fmt.Sprintf("%s:%d", hc.HarborHost, hc.HarborPort),
|
||||
Path: p,
|
||||
}
|
||||
}
|
||||
|
||||
// Get ...
|
||||
func (hc HarborClient) Get(p string) (*http.Response, error) {
|
||||
hbrURL := hc.harborURL(p)
|
||||
res, err := http.Get(hbrURL.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// InitHarborClient initialize the harbor client
|
||||
func InitHarborClient(hc *HarborClient) {
|
||||
hbrCli = hc
|
||||
}
|
46
src/pkg/exporter/harbor_cli_test.go
Normal file
46
src/pkg/exporter/harbor_cli_test.go
Normal file
@ -0,0 +1,46 @@
|
||||
package exporter
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHarborClient_harborURL(t *testing.T) {
|
||||
type fields struct {
|
||||
HarborScheme string
|
||||
HarborHost string
|
||||
HarborPort int
|
||||
Client *http.Client
|
||||
}
|
||||
type args struct {
|
||||
p string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
want string
|
||||
}{
|
||||
{name: "Can get URL", fields: fields{
|
||||
HarborScheme: "https",
|
||||
HarborHost: "test.harbor.dev",
|
||||
HarborPort: 8443,
|
||||
Client: http.DefaultClient,
|
||||
},
|
||||
args: args{p: ""}, want: "https://test.harbor.dev:8443",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
hc := HarborClient{
|
||||
HarborScheme: tt.fields.HarborScheme,
|
||||
HarborHost: tt.fields.HarborHost,
|
||||
HarborPort: tt.fields.HarborPort,
|
||||
Client: tt.fields.Client,
|
||||
}
|
||||
if got := hc.harborURL(tt.args.p); got.String() != tt.want {
|
||||
t.Errorf("HarborClient.harborURL() = %v, want %v", got.String(), tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
151
src/pkg/exporter/project_collector_test.go
Normal file
151
src/pkg/exporter/project_collector_test.go
Normal file
@ -0,0 +1,151 @@
|
||||
package exporter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/goharbor/harbor/src/common"
|
||||
"github.com/goharbor/harbor/src/common/dao"
|
||||
"github.com/goharbor/harbor/src/common/dao/project"
|
||||
"github.com/goharbor/harbor/src/common/models"
|
||||
"github.com/goharbor/harbor/src/common/utils/test"
|
||||
proctl "github.com/goharbor/harbor/src/controller/project"
|
||||
quotactl "github.com/goharbor/harbor/src/controller/quota"
|
||||
"github.com/goharbor/harbor/src/lib/orm"
|
||||
"github.com/goharbor/harbor/src/pkg/artifact"
|
||||
qtypes "github.com/goharbor/harbor/src/pkg/quota/types"
|
||||
"github.com/goharbor/harbor/src/pkg/repository"
|
||||
)
|
||||
|
||||
var (
|
||||
alice = models.User{Username: "alice", Password: "password", Email: "alice@test.com"}
|
||||
bob = models.User{Username: "bob", Password: "password", Email: "bob@test.com"}
|
||||
eve = models.User{Username: "eve", Password: "password", Email: "eve@test.com"}
|
||||
testPro1 = models.Project{OwnerID: 1, Name: "test1", Metadata: map[string]string{"public": "true"}}
|
||||
testPro2 = models.Project{OwnerID: 1, Name: "test2", Metadata: map[string]string{"public": "false"}}
|
||||
rs1 = qtypes.ResourceList{qtypes.ResourceStorage: 100}
|
||||
rs2 = qtypes.ResourceList{qtypes.ResourceStorage: 200}
|
||||
repo1 = models.RepoRecord{Name: "repo1"}
|
||||
repo2 = models.RepoRecord{Name: "repo2"}
|
||||
pmIDs = []int{}
|
||||
art1 = artifact.Artifact{RepositoryName: repo1.Name, Type: "IMAGE", Digest: "sha256:418fb88ec412e340cdbef913b8ca1bbe8f9e8dc705f9617414c1f2c8db980180"}
|
||||
art2 = artifact.Artifact{RepositoryName: repo1.Name, Type: "IMAGE", Digest: "sha256:3198b18471892718923712837192831287312893712893712897312db1a3bc73"}
|
||||
)
|
||||
|
||||
func setupTest(t *testing.T) {
|
||||
test.InitDatabaseFromEnv()
|
||||
|
||||
// register projAdmin and assign project admin role
|
||||
aliceID, err := dao.Register(alice)
|
||||
bobID, err := dao.Register(bob)
|
||||
eveID, err := dao.Register(eve)
|
||||
if err != nil {
|
||||
t.Errorf("register user error %v", err)
|
||||
}
|
||||
|
||||
// Create Project
|
||||
ctx := orm.NewContext(context.Background(), dao.GetOrmer())
|
||||
proID1, err := proctl.Ctl.Create(ctx, &testPro1)
|
||||
proID2, err := proctl.Ctl.Create(ctx, &testPro2)
|
||||
if err != nil {
|
||||
t.Errorf("project creating %v", err)
|
||||
}
|
||||
testPro1.ProjectID = proID1
|
||||
testPro2.ProjectID = proID2
|
||||
|
||||
// Create quota for project
|
||||
quotactl.Ctl.Create(ctx, "project", strconv.Itoa(int(testPro1.ProjectID)), rs1)
|
||||
quotactl.Ctl.Create(ctx, "project", strconv.Itoa(int(testPro2.ProjectID)), rs2)
|
||||
if err != nil {
|
||||
t.Errorf("add project error %v", err)
|
||||
}
|
||||
|
||||
// Add repo to project
|
||||
repo1.ProjectID = testPro1.ProjectID
|
||||
repo1ID, err := repository.Mgr.Create(ctx, &repo1)
|
||||
repo1.RepositoryID = repo1ID
|
||||
repo2.ProjectID = testPro2.ProjectID
|
||||
repo2ID, err := repository.Mgr.Create(ctx, &repo2)
|
||||
repo2.RepositoryID = repo2ID
|
||||
if err != nil {
|
||||
t.Errorf("add repo error %v", err)
|
||||
}
|
||||
// Add artifacts
|
||||
art1.ProjectID = testPro1.ProjectID
|
||||
art1.RepositoryID = repo1ID
|
||||
art1.PushTime = time.Now()
|
||||
_, err = artifact.Mgr.Create(ctx, &art1)
|
||||
|
||||
art2.ProjectID = testPro2.ProjectID
|
||||
art2.RepositoryID = repo2ID
|
||||
art2.PushTime = time.Now()
|
||||
_, err = artifact.Mgr.Create(ctx, &art2)
|
||||
if err != nil {
|
||||
t.Errorf("add repo error %v", err)
|
||||
}
|
||||
// Add member to project
|
||||
pmIDs = make([]int, 0)
|
||||
alice.UserID, bob.UserID, eve.UserID = int(aliceID), int(bobID), int(eveID)
|
||||
p1m1ID, err := project.AddProjectMember(models.Member{ProjectID: proID1, Role: common.RoleDeveloper, EntityID: int(aliceID), EntityType: common.UserMember})
|
||||
p2m1ID, err := project.AddProjectMember(models.Member{ProjectID: proID2, Role: common.RoleMaintainer, EntityID: int(bobID), EntityType: common.UserMember})
|
||||
p2m2ID, err := project.AddProjectMember(models.Member{ProjectID: proID2, Role: common.RoleMaintainer, EntityID: int(eveID), EntityType: common.UserMember})
|
||||
if err != nil {
|
||||
t.Errorf("add project member error %v", err)
|
||||
}
|
||||
pmIDs = append(pmIDs, p1m1ID, p2m1ID, p2m2ID)
|
||||
}
|
||||
|
||||
func tearDownTest(t *testing.T) {
|
||||
dao.GetOrmer().Raw("delete from project_member where project_id in (?, ?)", []int64{testPro1.ProjectID, testPro2.ProjectID}).Exec()
|
||||
dao.GetOrmer().Raw("delete from project_metadata where project_id in (?, ?)", []int64{testPro1.ProjectID, testPro2.ProjectID}).Exec()
|
||||
dao.GetOrmer().Raw("delete from quota where reference=\"project\" and reference_id in (?, ?)", []int64{testPro1.ProjectID, testPro2.ProjectID}).Exec()
|
||||
dao.GetOrmer().Raw("delete from quota_usage where reference=\"project\" and reference_id in (?, ?)", []int64{testPro1.ProjectID, testPro2.ProjectID}).Exec()
|
||||
dao.GetOrmer().Raw("delete from project where project_id in (?, ?)", []int64{testPro1.ProjectID, testPro2.ProjectID}).Exec()
|
||||
dao.GetOrmer().Raw("delete from artifact where project_id in (?, ?)", []int64{testPro1.ProjectID, testPro2.ProjectID}).Exec()
|
||||
dao.GetOrmer().Raw("delete from repository where project_id in (?, ?)", []int64{testPro1.ProjectID, testPro2.ProjectID}).Exec()
|
||||
dao.GetOrmer().Raw("delete from cve_allowlist where project_id in (?, ?)", []int64{testPro1.ProjectID, testPro2.ProjectID}).Exec()
|
||||
dao.GetOrmer().Raw("delete from harbor_user where user_id in (?, ?, ?)", []int{alice.UserID, bob.UserID, eve.UserID}).Exec()
|
||||
}
|
||||
|
||||
type PorjectCollectorTestSuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func (c *PorjectCollectorTestSuite) TestProjectCollector() {
|
||||
pMap := make(map[int64]*projectInfo)
|
||||
updateProjectBasicInfo(pMap)
|
||||
updateProjectMemberInfo(pMap)
|
||||
updateProjectRepoInfo(pMap)
|
||||
updateProjectArtifactInfo(pMap)
|
||||
|
||||
c.Equalf(testPro1.ProjectID, pMap[testPro1.ProjectID].ProjectID, "pMap %v", pMap)
|
||||
c.Equalf(pMap[testPro1.ProjectID].ProjectID, testPro1.ProjectID, "pMap %v", pMap)
|
||||
c.Equalf(pMap[testPro1.ProjectID].Name, testPro1.Name, "pMap %v", pMap)
|
||||
c.Equalf(strconv.FormatBool(pMap[testPro1.ProjectID].Public), testPro1.Metadata["public"], "pMap %v", pMap)
|
||||
c.Equalf(pMap[testPro1.ProjectID].Quota, "{\"storage\": 100}", "pMap %v", pMap)
|
||||
c.Equalf(pMap[testPro1.ProjectID].Usage, "{\"storage\": 0}", "pMap %v", pMap)
|
||||
c.Equalf(pMap[testPro1.ProjectID].MemberTotal, float64(2), "pMap %v", pMap)
|
||||
c.Equalf(pMap[testPro1.ProjectID].PullTotal, float64(0), "pMap %v", pMap)
|
||||
c.Equalf(pMap[testPro1.ProjectID].Artifact.ArtifactTotal, float64(1), "pMap %v", pMap)
|
||||
c.Equalf(pMap[testPro1.ProjectID].Artifact.ArtifactType, "IMAGE", "pMap %v", pMap)
|
||||
|
||||
c.Equalf(pMap[testPro2.ProjectID].ProjectID, testPro2.ProjectID, "pMap %v", pMap)
|
||||
c.Equalf(pMap[testPro2.ProjectID].Name, testPro2.Name, "pMap %v", pMap)
|
||||
c.Equalf(strconv.FormatBool(pMap[testPro2.ProjectID].Public), testPro2.Metadata["public"], "pMap %v", pMap)
|
||||
c.Equalf(pMap[testPro2.ProjectID].Quota, "{\"storage\": 200}", "pMap %v", pMap)
|
||||
c.Equalf(pMap[testPro2.ProjectID].Usage, "{\"storage\": 0}", "pMap %v", pMap)
|
||||
c.Equalf(pMap[testPro2.ProjectID].MemberTotal, float64(3), "pMap %v", pMap)
|
||||
c.Equalf(pMap[testPro2.ProjectID].PullTotal, float64(0), "pMap %v", pMap)
|
||||
c.Equalf(pMap[testPro2.ProjectID].Artifact.ArtifactTotal, float64(1), "pMap %v", pMap)
|
||||
|
||||
}
|
||||
|
||||
func TestPorjectCollectorTestSuite(t *testing.T) {
|
||||
setupTest(t)
|
||||
defer tearDownTest(t)
|
||||
suite.Run(t, new(PorjectCollectorTestSuite))
|
||||
}
|
110
src/pkg/exporter/system_collector_test.go
Normal file
110
src/pkg/exporter/system_collector_test.go
Normal file
@ -0,0 +1,110 @@
|
||||
package exporter
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type SysCollectorSuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func (c *SysCollectorSuite) SetupTest() {
|
||||
CacheInit(&Opt{
|
||||
CacheDuration: 1,
|
||||
})
|
||||
}
|
||||
|
||||
func TestNewSystemInfoCollector(t *testing.T) {
|
||||
type args struct {
|
||||
hbrCli *HarborClient
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *SystemInfoCollector
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := NewSystemInfoCollector(tt.args.hbrCli); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("NewSystemInfoCollector() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSystemInfoCollector_Describe(t *testing.T) {
|
||||
type fields struct {
|
||||
HarborClient *HarborClient
|
||||
}
|
||||
type args struct {
|
||||
c chan<- *prometheus.Desc
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
hc := &SystemInfoCollector{
|
||||
HarborClient: tt.fields.HarborClient,
|
||||
}
|
||||
hc.Describe(tt.args.c)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSystemInfoCollector_Collect(t *testing.T) {
|
||||
type fields struct {
|
||||
HarborClient *HarborClient
|
||||
}
|
||||
type args struct {
|
||||
c chan<- prometheus.Metric
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
hc := &SystemInfoCollector{
|
||||
HarborClient: tt.fields.HarborClient,
|
||||
}
|
||||
hc.Collect(tt.args.c)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSystemInfoCollector_getSysInfo(t *testing.T) {
|
||||
type fields struct {
|
||||
HarborClient *HarborClient
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want []prometheus.Metric
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
hc := &SystemInfoCollector{
|
||||
HarborClient: tt.fields.HarborClient,
|
||||
}
|
||||
if got := hc.getSysInfo(); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("SystemInfoCollector.getSysInfo() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user