mirror of
https://github.com/goharbor/harbor.git
synced 2025-03-02 10:41:59 +01:00
Merge pull request #4419 from ywk253100/180314_filter_by_label
Implement filter repository and tags by label API
This commit is contained in:
commit
8aa63b661c
@ -906,6 +906,11 @@ paths:
|
|||||||
type: string
|
type: string
|
||||||
required: false
|
required: false
|
||||||
description: Repo name for filtering results.
|
description: Repo name for filtering results.
|
||||||
|
- name: label_id
|
||||||
|
in: query
|
||||||
|
type: integer
|
||||||
|
required: false
|
||||||
|
description: The ID of label used to filter the result.
|
||||||
- name: page
|
- name: page
|
||||||
in: query
|
in: query
|
||||||
type: integer
|
type: integer
|
||||||
@ -1144,6 +1149,11 @@ paths:
|
|||||||
type: string
|
type: string
|
||||||
required: true
|
required: true
|
||||||
description: Relevant repository name.
|
description: Relevant repository name.
|
||||||
|
- name: label_ids
|
||||||
|
in: query
|
||||||
|
type: string
|
||||||
|
required: false
|
||||||
|
description: A list of comma separated label IDs.
|
||||||
tags:
|
tags:
|
||||||
- Products
|
- Products
|
||||||
responses:
|
responses:
|
||||||
|
@ -277,8 +277,9 @@ create table harbor_resource_label (
|
|||||||
label_id int NOT NULL,
|
label_id int NOT NULL,
|
||||||
# the resource_id is the ID of project when the resource_type is p
|
# the resource_id is the ID of project when the resource_type is p
|
||||||
# the resource_id is the ID of repository when the resource_type is r
|
# the resource_id is the ID of repository when the resource_type is r
|
||||||
# the resource_id is the name of image when the resource_type is i
|
resource_id int,
|
||||||
resource_id varchar(256) NOT NULL,
|
# the resource_name is the name of image when the resource_type is i
|
||||||
|
resource_name varchar(256),
|
||||||
# 'p' for project
|
# 'p' for project
|
||||||
# 'r' for repository
|
# 'r' for repository
|
||||||
# 'i' for image
|
# 'i' for image
|
||||||
|
@ -267,9 +267,12 @@ create table harbor_resource_label (
|
|||||||
/*
|
/*
|
||||||
the resource_id is the ID of project when the resource_type is p
|
the resource_id is the ID of project when the resource_type is p
|
||||||
the resource_id is the ID of repository when the resource_type is r
|
the resource_id is the ID of repository when the resource_type is r
|
||||||
the resource_id is the name of image when the resource_type is i
|
|
||||||
*/
|
*/
|
||||||
resource_id varchar(256) NOT NULL,
|
resource_id int,
|
||||||
|
/*
|
||||||
|
the resource_name is the name of image when the resource_type is i
|
||||||
|
*/
|
||||||
|
resource_name varchar(256),
|
||||||
/*
|
/*
|
||||||
'p' for project
|
'p' for project
|
||||||
'r' for repository
|
'r' for repository
|
||||||
|
@ -47,15 +47,6 @@ func GetRepositoryByName(name string) (*models.RepoRecord, error) {
|
|||||||
return &r, err
|
return &r, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllRepositories ...
|
|
||||||
func GetAllRepositories() ([]*models.RepoRecord, error) {
|
|
||||||
o := GetOrmer()
|
|
||||||
var repos []*models.RepoRecord
|
|
||||||
_, err := o.QueryTable("repository").Limit(-1).
|
|
||||||
OrderBy("Name").All(&repos)
|
|
||||||
return repos, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteRepository ...
|
// DeleteRepository ...
|
||||||
func DeleteRepository(name string) error {
|
func DeleteRepository(name string) error {
|
||||||
o := GetOrmer()
|
o := GetOrmer()
|
||||||
@ -94,18 +85,6 @@ func RepositoryExists(name string) bool {
|
|||||||
return o.QueryTable("repository").Filter("name", name).Exist()
|
return o.QueryTable("repository").Filter("name", name).Exist()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRepositoryByProjectName ...
|
|
||||||
func GetRepositoryByProjectName(name string) ([]*models.RepoRecord, error) {
|
|
||||||
sql := `select * from repository
|
|
||||||
where project_id = (
|
|
||||||
select project_id from project
|
|
||||||
where name = ?
|
|
||||||
)`
|
|
||||||
repos := []*models.RepoRecord{}
|
|
||||||
_, err := GetOrmer().Raw(sql, name).QueryRows(&repos)
|
|
||||||
return repos, err
|
|
||||||
}
|
|
||||||
|
|
||||||
//GetTopRepos returns the most popular repositories whose project ID is
|
//GetTopRepos returns the most popular repositories whose project ID is
|
||||||
// in projectIDs
|
// in projectIDs
|
||||||
func GetTopRepos(projectIDs []int64, n int) ([]*models.RepoRecord, error) {
|
func GetTopRepos(projectIDs []int64, n int) ([]*models.RepoRecord, error) {
|
||||||
@ -124,46 +103,78 @@ func GetTopRepos(projectIDs []int64, n int) ([]*models.RepoRecord, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetTotalOfRepositories ...
|
// GetTotalOfRepositories ...
|
||||||
func GetTotalOfRepositories(name string) (int64, error) {
|
func GetTotalOfRepositories(query ...*models.RepositoryQuery) (int64, error) {
|
||||||
qs := GetOrmer().QueryTable(&models.RepoRecord{})
|
sql, params := repositoryQueryConditions(query...)
|
||||||
if len(name) != 0 {
|
sql = `select count(*) ` + sql
|
||||||
qs = qs.Filter("Name__contains", name)
|
var total int64
|
||||||
|
if err := GetOrmer().Raw(sql, params).QueryRow(&total); err != nil {
|
||||||
|
return 0, err
|
||||||
}
|
}
|
||||||
return qs.Count()
|
return total, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTotalOfRepositoriesByProject ...
|
// GetRepositories ...
|
||||||
func GetTotalOfRepositoriesByProject(projectIDs []int64, name string) (int64, error) {
|
func GetRepositories(query ...*models.RepositoryQuery) ([]*models.RepoRecord, error) {
|
||||||
if len(projectIDs) == 0 {
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
qs := GetOrmer().QueryTable(&models.RepoRecord{}).
|
|
||||||
Filter("project_id__in", projectIDs)
|
|
||||||
|
|
||||||
if len(name) != 0 {
|
|
||||||
qs = qs.Filter("Name__contains", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return qs.Count()
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRepositoriesByProject ...
|
|
||||||
func GetRepositoriesByProject(projectID int64, name string,
|
|
||||||
limit, offset int64) ([]*models.RepoRecord, error) {
|
|
||||||
|
|
||||||
repositories := []*models.RepoRecord{}
|
repositories := []*models.RepoRecord{}
|
||||||
|
|
||||||
qs := GetOrmer().QueryTable(&models.RepoRecord{}).
|
sql, params := repositoryQueryConditions(query...)
|
||||||
Filter("ProjectID", projectID)
|
sql = `select r.repository_id, r.name, r.project_id, r.description, r.pull_count,
|
||||||
|
r.star_count, r.creation_time, r.update_time ` + sql + `order by r.name `
|
||||||
if len(name) != 0 {
|
if len(query) > 0 && query[0] != nil {
|
||||||
qs = qs.Filter("Name__contains", name)
|
page, size := query[0].Page, query[0].Size
|
||||||
|
if size > 0 {
|
||||||
|
sql += `limit ? `
|
||||||
|
params = append(params, size)
|
||||||
|
if page > 0 {
|
||||||
|
sql += `offset ? `
|
||||||
|
params = append(params, size*(page-1))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if limit > 0 {
|
|
||||||
qs = qs.Limit(limit).Offset(offset)
|
|
||||||
}
|
|
||||||
_, err := qs.All(&repositories)
|
|
||||||
|
|
||||||
return repositories, err
|
if _, err := GetOrmer().Raw(sql, params).QueryRows(&repositories); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return repositories, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func repositoryQueryConditions(query ...*models.RepositoryQuery) (string, []interface{}) {
|
||||||
|
params := []interface{}{}
|
||||||
|
sql := `from repository r `
|
||||||
|
if len(query) == 0 || query[0] == nil {
|
||||||
|
return sql, params
|
||||||
|
}
|
||||||
|
q := query[0]
|
||||||
|
if len(q.ProjectName) > 0 {
|
||||||
|
sql += `join project p on r.project_id = p.project_id `
|
||||||
|
}
|
||||||
|
|
||||||
|
if q.LabelID > 0 {
|
||||||
|
sql += `join harbor_resource_label rl on r.repository_id = rl.resource_id
|
||||||
|
and rl.resource_type = 'r' `
|
||||||
|
}
|
||||||
|
sql += `where 1=1 `
|
||||||
|
|
||||||
|
if len(q.Name) > 0 {
|
||||||
|
sql += `and r.name = ? `
|
||||||
|
params = append(params, q.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(q.ProjectIDs) > 0 {
|
||||||
|
sql += fmt.Sprintf(`and r.project_id in ( %s ) `,
|
||||||
|
paramPlaceholder(len(q.ProjectIDs)))
|
||||||
|
params = append(params, q.ProjectIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(q.ProjectName) > 0 {
|
||||||
|
sql += `and p.name = ? `
|
||||||
|
params = append(params, q.ProjectName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if q.LabelID > 0 {
|
||||||
|
sql += `and rl.label_id = ? `
|
||||||
|
params = append(params, q.LabelID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sql, params
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,11 @@ package dao
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/vmware/harbor/src/common"
|
||||||
"github.com/vmware/harbor/src/common/models"
|
"github.com/vmware/harbor/src/common/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,61 +33,93 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetRepositoryByProjectName(t *testing.T) {
|
func TestGetTotalOfRepositories(t *testing.T) {
|
||||||
if err := addRepository(repository); err != nil {
|
total, err := GetTotalOfRepositories()
|
||||||
t.Fatalf("failed to add repository %s: %v", name, err)
|
require.Nil(t, err)
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if err := deleteRepository(name); err != nil {
|
|
||||||
t.Fatalf("failed to delete repository %s: %v", name, err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
repositories, err := GetRepositoryByProjectName(project)
|
err = addRepository(repository)
|
||||||
if err != nil {
|
require.Nil(t, err)
|
||||||
t.Fatalf("failed to get repositories of project %s: %v",
|
defer deleteRepository(name)
|
||||||
project, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(repositories) == 0 {
|
n, err := GetTotalOfRepositories()
|
||||||
t.Fatal("unexpected length of repositories: 0, at least 1")
|
require.Nil(t, err)
|
||||||
}
|
assert.Equal(t, total+1, n)
|
||||||
|
}
|
||||||
|
|
||||||
exist := false
|
func TestGetRepositories(t *testing.T) {
|
||||||
for _, repo := range repositories {
|
// no query
|
||||||
if repo.Name == name {
|
repositories, err := GetRepositories()
|
||||||
exist = true
|
require.Nil(t, err)
|
||||||
|
n := len(repositories)
|
||||||
|
|
||||||
|
err = addRepository(repository)
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer deleteRepository(name)
|
||||||
|
|
||||||
|
repositories, err = GetRepositories()
|
||||||
|
require.Nil(t, err)
|
||||||
|
assert.Equal(t, n+1, len(repositories))
|
||||||
|
|
||||||
|
// query by name
|
||||||
|
repositories, err = GetRepositories(&models.RepositoryQuery{
|
||||||
|
Name: name,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, 1, len(repositories))
|
||||||
|
assert.Equal(t, name, repositories[0].Name)
|
||||||
|
|
||||||
|
// query by project name
|
||||||
|
repositories, err = GetRepositories(&models.RepositoryQuery{
|
||||||
|
ProjectName: project,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
found := false
|
||||||
|
for _, repository := range repositories {
|
||||||
|
if repository.Name == name {
|
||||||
|
found = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !exist {
|
assert.True(t, found)
|
||||||
t.Errorf("there is no repository whose name is %s", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetTotalOfRepositories(t *testing.T) {
|
// query by project ID
|
||||||
total, err := GetTotalOfRepositories("")
|
repositories, err = GetRepositories(&models.RepositoryQuery{
|
||||||
if err != nil {
|
ProjectIDs: []int64{1},
|
||||||
t.Fatalf("failed to get total of repositoreis: %v", err)
|
})
|
||||||
}
|
require.Nil(t, err)
|
||||||
|
found = false
|
||||||
if err := addRepository(repository); err != nil {
|
for _, repository := range repositories {
|
||||||
t.Fatalf("failed to add repository %s: %v", name, err)
|
if repository.Name == name {
|
||||||
}
|
found = true
|
||||||
defer func() {
|
break
|
||||||
if err := deleteRepository(name); err != nil {
|
|
||||||
t.Fatalf("failed to delete repository %s: %v", name, err)
|
|
||||||
}
|
}
|
||||||
}()
|
|
||||||
|
|
||||||
n, err := GetTotalOfRepositories("")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to get total of repositoreis: %v", err)
|
|
||||||
}
|
}
|
||||||
|
assert.True(t, found)
|
||||||
|
|
||||||
if n != total+1 {
|
// query by label ID
|
||||||
t.Errorf("unexpected total: %d != %d", n, total+1)
|
labelID, err := AddLabel(&models.Label{
|
||||||
}
|
Name: "label_for_test",
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer DeleteLabel(labelID)
|
||||||
|
|
||||||
|
r, err := GetRepositoryByName(name)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
rlID, err := AddResourceLabel(&models.ResourceLabel{
|
||||||
|
LabelID: labelID,
|
||||||
|
ResourceID: r.RepositoryID,
|
||||||
|
ResourceType: common.ResourceTypeRepository,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer DeleteResourceLabel(rlID)
|
||||||
|
|
||||||
|
repositories, err = GetRepositories(&models.RepositoryQuery{
|
||||||
|
LabelID: labelID,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, 1, len(repositories))
|
||||||
|
assert.Equal(t, name, repositories[0].Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTopRepos(t *testing.T) {
|
func TestGetTopRepos(t *testing.T) {
|
||||||
@ -149,112 +182,6 @@ func TestGetTopRepos(t *testing.T) {
|
|||||||
require.Equal(topRepos[0].Name, repository3.Name)
|
require.Equal(topRepos[0].Name, repository3.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTotalOfRepositoriesByProject(t *testing.T) {
|
|
||||||
var projectID int64 = 1
|
|
||||||
repoName := "library/total_count"
|
|
||||||
|
|
||||||
total, err := GetTotalOfRepositoriesByProject([]int64{projectID}, repoName)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("failed to get total of repositoreis of project %d: %v", projectID, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := addRepository(&models.RepoRecord{
|
|
||||||
Name: repoName,
|
|
||||||
ProjectID: projectID,
|
|
||||||
}); err != nil {
|
|
||||||
t.Errorf("failed to add repository %s: %v", repoName, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if err := deleteRepository(repoName); err != nil {
|
|
||||||
t.Errorf("failed to delete repository %s: %v", name, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
n, err := GetTotalOfRepositoriesByProject([]int64{projectID}, repoName)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("failed to get total of repositoreis of project %d: %v", projectID, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if n != total+1 {
|
|
||||||
t.Errorf("unexpected total: %d != %d", n, total+1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetRepositoriesByProject(t *testing.T) {
|
|
||||||
var projectID int64 = 1
|
|
||||||
repoName := "library/repository"
|
|
||||||
|
|
||||||
if err := addRepository(&models.RepoRecord{
|
|
||||||
Name: repoName,
|
|
||||||
ProjectID: projectID,
|
|
||||||
}); err != nil {
|
|
||||||
t.Errorf("failed to add repository %s: %v", repoName, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if err := deleteRepository(repoName); err != nil {
|
|
||||||
t.Errorf("failed to delete repository %s: %v", name, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
repositories, err := GetRepositoriesByProject(projectID, repoName, 10, 0)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("failed to get repositoreis of project %d: %v", projectID, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Log(repositories)
|
|
||||||
|
|
||||||
for _, repository := range repositories {
|
|
||||||
if repository.Name == repoName {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Errorf("repository %s not found", repoName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetAllRepositories(t *testing.T) {
|
|
||||||
require := require.New(t)
|
|
||||||
|
|
||||||
var repos []*models.RepoRecord
|
|
||||||
repos, err := GetAllRepositories()
|
|
||||||
require.NoError(err)
|
|
||||||
allBefore := len(repos)
|
|
||||||
|
|
||||||
project1 := models.Project{
|
|
||||||
OwnerID: 1,
|
|
||||||
Name: "projectRepo",
|
|
||||||
}
|
|
||||||
var err2 error
|
|
||||||
project1.ProjectID, err2 = AddProject(project1)
|
|
||||||
require.NoError(err2)
|
|
||||||
|
|
||||||
for i := 0; i < 1200; i++ {
|
|
||||||
end := strconv.Itoa(i)
|
|
||||||
repoRecord := models.RepoRecord{
|
|
||||||
Name: "test" + end,
|
|
||||||
ProjectID: project1.ProjectID,
|
|
||||||
}
|
|
||||||
err := AddRepository(repoRecord)
|
|
||||||
require.NoError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
repos, err = GetAllRepositories()
|
|
||||||
require.NoError(err)
|
|
||||||
allAfter := len(repos)
|
|
||||||
|
|
||||||
require.Equal(allAfter, allBefore+1200)
|
|
||||||
|
|
||||||
err = clearRepositoryData()
|
|
||||||
require.NoError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func addRepository(repository *models.RepoRecord) error {
|
func addRepository(repository *models.RepoRecord) error {
|
||||||
return AddRepository(*repository)
|
return AddRepository(*repository)
|
||||||
}
|
}
|
||||||
|
@ -29,14 +29,26 @@ func AddResourceLabel(rl *models.ResourceLabel) (int64, error) {
|
|||||||
return GetOrmer().Insert(rl)
|
return GetOrmer().Insert(rl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetResourceLabel specified by ID
|
// GetResourceLabel specified by resource ID or name
|
||||||
func GetResourceLabel(rType, rID string, labelID int64) (*models.ResourceLabel, error) {
|
// Get the ResourceLabel by ResourceID if rIDOrName is int
|
||||||
|
// Get the ResourceLabel by ResourceName if rIDOrName is string
|
||||||
|
func GetResourceLabel(rType string, rIDOrName interface{}, labelID int64) (*models.ResourceLabel, error) {
|
||||||
rl := &models.ResourceLabel{
|
rl := &models.ResourceLabel{
|
||||||
ResourceType: rType,
|
ResourceType: rType,
|
||||||
ResourceID: rID,
|
|
||||||
LabelID: labelID,
|
LabelID: labelID,
|
||||||
}
|
}
|
||||||
if err := GetOrmer().Read(rl, "ResourceType", "ResourceID", "LabelID"); err != nil {
|
|
||||||
|
var err error
|
||||||
|
id, ok := rIDOrName.(int64)
|
||||||
|
if ok {
|
||||||
|
rl.ResourceID = id
|
||||||
|
err = GetOrmer().Read(rl, "ResourceType", "ResourceID", "LabelID")
|
||||||
|
} else {
|
||||||
|
rl.ResourceName = rIDOrName.(string)
|
||||||
|
err = GetOrmer().Read(rl, "ResourceType", "ResourceName", "LabelID")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
if err == orm.ErrNoRows {
|
if err == orm.ErrNoRows {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@ -47,13 +59,20 @@ func GetResourceLabel(rType, rID string, labelID int64) (*models.ResourceLabel,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetLabelsOfResource returns the label list of the resource
|
// GetLabelsOfResource returns the label list of the resource
|
||||||
func GetLabelsOfResource(rType, rID string) ([]*models.Label, error) {
|
// Get the labels by ResourceID if rIDOrName is int, or get the labels by ResourceName
|
||||||
|
func GetLabelsOfResource(rType string, rIDOrName interface{}) ([]*models.Label, error) {
|
||||||
sql := `select l.id, l.name, l.description, l.color, l.scope, l.project_id, l.creation_time, l.update_time
|
sql := `select l.id, l.name, l.description, l.color, l.scope, l.project_id, l.creation_time, l.update_time
|
||||||
from harbor_resource_label rl
|
from harbor_resource_label rl
|
||||||
join harbor_label l on rl.label_id=l.id
|
join harbor_label l on rl.label_id=l.id
|
||||||
where rl.resource_type = ? and rl.resource_id = ?`
|
where rl.resource_type = ? and`
|
||||||
|
if _, ok := rIDOrName.(int64); ok {
|
||||||
|
sql += ` rl.resource_id = ?`
|
||||||
|
} else {
|
||||||
|
sql += ` rl.resource_name = ?`
|
||||||
|
}
|
||||||
|
|
||||||
labels := []*models.Label{}
|
labels := []*models.Label{}
|
||||||
_, err := GetOrmer().Raw(sql, rType, rID).QueryRows(&labels)
|
_, err := GetOrmer().Raw(sql, rType, rIDOrName).QueryRows(&labels)
|
||||||
return labels, err
|
return labels, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,10 +84,39 @@ func DeleteResourceLabel(id int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteLabelsOfResource removes all labels of resource specified by rType and rID
|
// DeleteLabelsOfResource removes all labels of the resource
|
||||||
func DeleteLabelsOfResource(rType, rID string) error {
|
func DeleteLabelsOfResource(rType string, rIDOrName interface{}) error {
|
||||||
_, err := GetOrmer().QueryTable(&models.ResourceLabel{}).
|
qs := GetOrmer().QueryTable(&models.ResourceLabel{}).
|
||||||
Filter("ResourceType", rType).
|
Filter("ResourceType", rType)
|
||||||
Filter("ResourceID", rID).Delete()
|
if _, ok := rIDOrName.(int64); ok {
|
||||||
|
qs = qs.Filter("ResourceID", rIDOrName)
|
||||||
|
} else {
|
||||||
|
qs = qs.Filter("ResourceName", rIDOrName)
|
||||||
|
}
|
||||||
|
_, err := qs.Delete()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListResourceLabels lists ResourceLabel according to the query conditions
|
||||||
|
func ListResourceLabels(query ...*models.ResourceLabelQuery) ([]*models.ResourceLabel, error) {
|
||||||
|
qs := GetOrmer().QueryTable(&models.ResourceLabel{})
|
||||||
|
if len(query) > 0 {
|
||||||
|
q := query[0]
|
||||||
|
if q.LabelID > 0 {
|
||||||
|
qs = qs.Filter("LabelID", q.LabelID)
|
||||||
|
}
|
||||||
|
if len(q.ResourceType) > 0 {
|
||||||
|
qs = qs.Filter("ResourceType", q.ResourceType)
|
||||||
|
}
|
||||||
|
if q.ResourceID > 0 {
|
||||||
|
qs = qs.Filter("ResourceID", q.ResourceID)
|
||||||
|
}
|
||||||
|
if len(q.ResourceName) > 0 {
|
||||||
|
qs = qs.Filter("ResourceName", q.ResourceName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rls := []*models.ResourceLabel{}
|
||||||
|
_, err := qs.All(&rls)
|
||||||
|
return rls, err
|
||||||
|
}
|
||||||
|
@ -32,7 +32,7 @@ func TestMethodsOfResourceLabel(t *testing.T) {
|
|||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
defer DeleteLabel(labelID)
|
defer DeleteLabel(labelID)
|
||||||
|
|
||||||
resourceID := "1"
|
var resourceID int64 = 1
|
||||||
resourceType := common.ResourceTypeRepository
|
resourceType := common.ResourceTypeRepository
|
||||||
|
|
||||||
// add
|
// add
|
||||||
@ -56,6 +56,16 @@ func TestMethodsOfResourceLabel(t *testing.T) {
|
|||||||
require.Equal(t, 1, len(labels))
|
require.Equal(t, 1, len(labels))
|
||||||
assert.Equal(t, id, r.ID)
|
assert.Equal(t, id, r.ID)
|
||||||
|
|
||||||
|
// list
|
||||||
|
rls, err := ListResourceLabels(&models.ResourceLabelQuery{
|
||||||
|
LabelID: labelID,
|
||||||
|
ResourceType: resourceType,
|
||||||
|
ResourceID: resourceID,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, 1, len(rls))
|
||||||
|
assert.Equal(t, id, rls[0].ID)
|
||||||
|
|
||||||
// delete
|
// delete
|
||||||
err = DeleteResourceLabel(id)
|
err = DeleteResourceLabel(id)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
@ -69,7 +69,8 @@ func (l *Label) Valid(v *validation.Validation) {
|
|||||||
type ResourceLabel struct {
|
type ResourceLabel struct {
|
||||||
ID int64 `orm:"pk;auto;column(id)"`
|
ID int64 `orm:"pk;auto;column(id)"`
|
||||||
LabelID int64 `orm:"column(label_id)"`
|
LabelID int64 `orm:"column(label_id)"`
|
||||||
ResourceID string `orm:"column(resource_id)"`
|
ResourceID int64 `orm:"column(resource_id)"`
|
||||||
|
ResourceName string `orm:"column(resource_name)"`
|
||||||
ResourceType string `orm:"column(resource_type)"`
|
ResourceType string `orm:"column(resource_type)"`
|
||||||
CreationTime time.Time `orm:"column(creation_time)"`
|
CreationTime time.Time `orm:"column(creation_time)"`
|
||||||
UpdateTime time.Time `orm:"column(update_time)"`
|
UpdateTime time.Time `orm:"column(update_time)"`
|
||||||
@ -79,3 +80,11 @@ type ResourceLabel struct {
|
|||||||
func (r *ResourceLabel) TableName() string {
|
func (r *ResourceLabel) TableName() string {
|
||||||
return "harbor_resource_label"
|
return "harbor_resource_label"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResourceLabelQuery : query parameters for the mapping relationships of resource and label
|
||||||
|
type ResourceLabelQuery struct {
|
||||||
|
LabelID int64
|
||||||
|
ResourceID int64
|
||||||
|
ResourceName string
|
||||||
|
ResourceType string
|
||||||
|
}
|
||||||
|
@ -33,7 +33,7 @@ type Project struct {
|
|||||||
OwnerName string `orm:"-" json:"owner_name"`
|
OwnerName string `orm:"-" json:"owner_name"`
|
||||||
Togglable bool `orm:"-" json:"togglable"`
|
Togglable bool `orm:"-" json:"togglable"`
|
||||||
Role int `orm:"-" json:"current_user_role_id"`
|
Role int `orm:"-" json:"current_user_role_id"`
|
||||||
RepoCount int `orm:"-" json:"repo_count"`
|
RepoCount int64 `orm:"-" json:"repo_count"`
|
||||||
Metadata map[string]string `orm:"-" json:"metadata"`
|
Metadata map[string]string `orm:"-" json:"metadata"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,3 +37,12 @@ type RepoRecord struct {
|
|||||||
func (rp *RepoRecord) TableName() string {
|
func (rp *RepoRecord) TableName() string {
|
||||||
return RepoTable
|
return RepoTable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RepositoryQuery : query parameters for repository
|
||||||
|
type RepositoryQuery struct {
|
||||||
|
Name string
|
||||||
|
ProjectIDs []int64
|
||||||
|
ProjectName string
|
||||||
|
LabelID int64
|
||||||
|
Pagination
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@ package registry
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/vmware/harbor/src/common/dao"
|
"github.com/vmware/harbor/src/common/dao"
|
||||||
|
common_models "github.com/vmware/harbor/src/common/models"
|
||||||
"github.com/vmware/harbor/src/common/utils/log"
|
"github.com/vmware/harbor/src/common/utils/log"
|
||||||
"github.com/vmware/harbor/src/replication"
|
"github.com/vmware/harbor/src/replication"
|
||||||
"github.com/vmware/harbor/src/replication/models"
|
"github.com/vmware/harbor/src/replication/models"
|
||||||
@ -30,7 +31,9 @@ func (ha *HarborAdaptor) GetNamespace(name string) models.Namespace {
|
|||||||
|
|
||||||
//GetRepositories is used to get all the repositories under the specified namespace
|
//GetRepositories is used to get all the repositories under the specified namespace
|
||||||
func (ha *HarborAdaptor) GetRepositories(namespace string) []models.Repository {
|
func (ha *HarborAdaptor) GetRepositories(namespace string) []models.Repository {
|
||||||
repos, err := dao.GetRepositoryByProjectName(namespace)
|
repos, err := dao.GetRepositories(&common_models.RepositoryQuery{
|
||||||
|
ProjectName: namespace,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed to get repositories under namespace %s: %v", namespace, err)
|
log.Errorf("failed to get repositories under namespace %s: %v", namespace, err)
|
||||||
return nil
|
return nil
|
||||||
|
@ -270,7 +270,9 @@ func (p *ProjectAPI) Deletable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func deletable(projectID int64) (*deletableResp, error) {
|
func deletable(projectID int64) (*deletableResp, error) {
|
||||||
count, err := dao.GetTotalOfRepositoriesByProject([]int64{projectID}, "")
|
count, err := dao.GetTotalOfRepositories(&models.RepositoryQuery{
|
||||||
|
ProjectIDs: []int64{projectID},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -395,13 +397,15 @@ func (p *ProjectAPI) populateProperties(project *models.Project) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
repos, err := dao.GetRepositoryByProjectName(project.Name)
|
total, err := dao.GetTotalOfRepositories(&models.RepositoryQuery{
|
||||||
|
ProjectIDs: []int64{project.ProjectID},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed to get repositories of project %s: %v", project.Name, err)
|
log.Errorf("failed to get total of repositories of project %d: %v", project.ProjectID, err)
|
||||||
p.CustomAbort(http.StatusInternalServerError, "")
|
p.CustomAbort(http.StatusInternalServerError, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
project.RepoCount = len(repos)
|
project.RepoCount = total
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put ...
|
// Put ...
|
||||||
|
@ -96,6 +96,12 @@ func (ra *RepositoryAPI) Get() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
labelID, err := ra.GetInt64("label_id", 0)
|
||||||
|
if err != nil {
|
||||||
|
ra.HandleBadRequest(fmt.Sprintf("invalid label_id: %s", ra.GetString("label_id")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
exist, err := ra.ProjectMgr.Exists(projectID)
|
exist, err := ra.ProjectMgr.Exists(projectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ra.ParseAndHandleError(fmt.Sprintf("failed to check the existence of project %d",
|
ra.ParseAndHandleError(fmt.Sprintf("failed to check the existence of project %d",
|
||||||
@ -117,33 +123,33 @@ func (ra *RepositoryAPI) Get() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
keyword := ra.GetString("q")
|
query := &models.RepositoryQuery{
|
||||||
|
ProjectIDs: []int64{projectID},
|
||||||
|
Name: ra.GetString("q"),
|
||||||
|
LabelID: labelID,
|
||||||
|
}
|
||||||
|
query.Page, query.Size = ra.GetPaginationParams()
|
||||||
|
|
||||||
total, err := dao.GetTotalOfRepositoriesByProject(
|
total, err := dao.GetTotalOfRepositories(query)
|
||||||
[]int64{projectID}, keyword)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ra.HandleInternalServerError(fmt.Sprintf("failed to get total of repositories of project %d: %v",
|
ra.HandleInternalServerError(fmt.Sprintf("failed to get total of repositories of project %d: %v",
|
||||||
projectID, err))
|
projectID, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
page, pageSize := ra.GetPaginationParams()
|
repositories, err := getRepositories(query)
|
||||||
|
|
||||||
repositories, err := getRepositories(projectID,
|
|
||||||
keyword, pageSize, pageSize*(page-1))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ra.HandleInternalServerError(fmt.Sprintf("failed to get repository: %v", err))
|
ra.HandleInternalServerError(fmt.Sprintf("failed to get repository: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ra.SetPaginationHeader(total, page, pageSize)
|
ra.SetPaginationHeader(total, query.Page, query.Size)
|
||||||
ra.Data["json"] = repositories
|
ra.Data["json"] = repositories
|
||||||
ra.ServeJSON()
|
ra.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRepositories(projectID int64, keyword string,
|
func getRepositories(query *models.RepositoryQuery) ([]*repoResp, error) {
|
||||||
limit, offset int64) ([]*repoResp, error) {
|
repositories, err := dao.GetRepositories(query)
|
||||||
repositories, err := dao.GetRepositoriesByProject(projectID, keyword, limit, offset)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -171,8 +177,7 @@ func assembleRepos(repositories []*models.RepoRecord) ([]*repoResp, error) {
|
|||||||
}
|
}
|
||||||
repo.TagsCount = int64(len(tags))
|
repo.TagsCount = int64(len(tags))
|
||||||
|
|
||||||
labels, err := dao.GetLabelsOfResource(common.ResourceTypeRepository,
|
labels, err := dao.GetLabelsOfResource(common.ResourceTypeRepository, repository.RepositoryID)
|
||||||
strconv.FormatInt(repository.RepositoryID, 10))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed to get labels of repository %s: %v", repository.Name, err)
|
log.Errorf("failed to get labels of repository %s: %v", repository.Name, err)
|
||||||
} else {
|
} else {
|
||||||
@ -385,6 +390,11 @@ func (ra *RepositoryAPI) GetTag() {
|
|||||||
// GetTags returns tags of a repository
|
// GetTags returns tags of a repository
|
||||||
func (ra *RepositoryAPI) GetTags() {
|
func (ra *RepositoryAPI) GetTags() {
|
||||||
repoName := ra.GetString(":splat")
|
repoName := ra.GetString(":splat")
|
||||||
|
labelID, err := ra.GetInt64("label_id", 0)
|
||||||
|
if err != nil {
|
||||||
|
ra.HandleBadRequest(fmt.Sprintf("invalid label_id: %s", ra.GetString("label_id")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
projectName, _ := utils.ParseRepository(repoName)
|
projectName, _ := utils.ParseRepository(repoName)
|
||||||
exist, err := ra.ProjectMgr.Exists(projectName)
|
exist, err := ra.ProjectMgr.Exists(projectName)
|
||||||
@ -420,7 +430,31 @@ func (ra *RepositoryAPI) GetTags() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ra.Data["json"] = assembleTags(client, repoName, tags, ra.SecurityCtx.GetUsername())
|
// filter tags by label ID
|
||||||
|
if labelID > 0 {
|
||||||
|
rls, err := dao.ListResourceLabels(&models.ResourceLabelQuery{
|
||||||
|
LabelID: labelID,
|
||||||
|
ResourceType: common.ResourceTypeImage,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ra.HandleInternalServerError(fmt.Sprintf("failed to list resource labels: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
labeledTags := map[string]struct{}{}
|
||||||
|
for _, rl := range rls {
|
||||||
|
labeledTags[strings.Split(rl.ResourceName, ":")[1]] = struct{}{}
|
||||||
|
}
|
||||||
|
ts := []string{}
|
||||||
|
for _, tag := range tags {
|
||||||
|
if _, ok := labeledTags[tag]; ok {
|
||||||
|
ts = append(ts, tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tags = ts
|
||||||
|
}
|
||||||
|
|
||||||
|
ra.Data["json"] = assembleTags(client, repoName, tags,
|
||||||
|
ra.SecurityCtx.GetUsername())
|
||||||
ra.ServeJSON()
|
ra.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,6 +477,15 @@ func assembleTags(client *registry.Repository, repository string,
|
|||||||
for _, t := range tags {
|
for _, t := range tags {
|
||||||
item := &tagResp{}
|
item := &tagResp{}
|
||||||
|
|
||||||
|
// labels
|
||||||
|
image := fmt.Sprintf("%s:%s", repository, t)
|
||||||
|
labels, err := dao.GetLabelsOfResource(common.ResourceTypeImage, image)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to get labels of image %s: %v", image, err)
|
||||||
|
} else {
|
||||||
|
item.Labels = labels
|
||||||
|
}
|
||||||
|
|
||||||
// the detail information of tag
|
// the detail information of tag
|
||||||
tagDetail, err := getTagDetail(client, t)
|
tagDetail, err := getTagDetail(client, t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -468,15 +511,6 @@ func assembleTags(client *registry.Repository, repository string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// labels
|
|
||||||
image := fmt.Sprintf("%s:%s", repository, t)
|
|
||||||
labels, err := dao.GetLabelsOfResource(common.ResourceTypeImage, image)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed to get labels of image %s: %v", image, err)
|
|
||||||
} else {
|
|
||||||
item.Labels = labels
|
|
||||||
}
|
|
||||||
|
|
||||||
result = append(result, item)
|
result = append(result, item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,24 +144,20 @@ func (r *RepositoryLabelAPI) AddToImage() {
|
|||||||
rl := &models.ResourceLabel{
|
rl := &models.ResourceLabel{
|
||||||
LabelID: r.label.ID,
|
LabelID: r.label.ID,
|
||||||
ResourceType: common.ResourceTypeImage,
|
ResourceType: common.ResourceTypeImage,
|
||||||
ResourceID: fmt.Sprintf("%s:%s", r.repository.Name, r.tag),
|
ResourceName: fmt.Sprintf("%s:%s", r.repository.Name, r.tag),
|
||||||
}
|
}
|
||||||
r.addLabel(rl)
|
r.addLabel(rl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveFromImage removes the label from an image
|
// RemoveFromImage removes the label from an image
|
||||||
func (r *RepositoryLabelAPI) RemoveFromImage() {
|
func (r *RepositoryLabelAPI) RemoveFromImage() {
|
||||||
rl := &models.ResourceLabel{
|
r.removeLabel(common.ResourceTypeImage,
|
||||||
LabelID: r.label.ID,
|
fmt.Sprintf("%s:%s", r.repository.Name, r.tag), r.label.ID)
|
||||||
ResourceType: common.ResourceTypeImage,
|
|
||||||
ResourceID: fmt.Sprintf("%s:%s", r.repository.Name, r.tag),
|
|
||||||
}
|
|
||||||
r.removeLabel(rl)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOfRepository returns labels of a repository
|
// GetOfRepository returns labels of a repository
|
||||||
func (r *RepositoryLabelAPI) GetOfRepository() {
|
func (r *RepositoryLabelAPI) GetOfRepository() {
|
||||||
r.getLabels(common.ResourceTypeRepository, strconv.FormatInt(r.repository.RepositoryID, 10))
|
r.getLabels(common.ResourceTypeRepository, r.repository.RepositoryID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddToRepository adds the label to a repository
|
// AddToRepository adds the label to a repository
|
||||||
@ -169,26 +165,21 @@ func (r *RepositoryLabelAPI) AddToRepository() {
|
|||||||
rl := &models.ResourceLabel{
|
rl := &models.ResourceLabel{
|
||||||
LabelID: r.label.ID,
|
LabelID: r.label.ID,
|
||||||
ResourceType: common.ResourceTypeRepository,
|
ResourceType: common.ResourceTypeRepository,
|
||||||
ResourceID: strconv.FormatInt(r.repository.RepositoryID, 10),
|
ResourceID: r.repository.RepositoryID,
|
||||||
}
|
}
|
||||||
r.addLabel(rl)
|
r.addLabel(rl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveFromRepository removes the label from a repository
|
// RemoveFromRepository removes the label from a repository
|
||||||
func (r *RepositoryLabelAPI) RemoveFromRepository() {
|
func (r *RepositoryLabelAPI) RemoveFromRepository() {
|
||||||
rl := &models.ResourceLabel{
|
r.removeLabel(common.ResourceTypeRepository, r.repository.RepositoryID, r.label.ID)
|
||||||
LabelID: r.label.ID,
|
|
||||||
ResourceType: common.ResourceTypeRepository,
|
|
||||||
ResourceID: strconv.FormatInt(r.repository.RepositoryID, 10),
|
|
||||||
}
|
|
||||||
r.removeLabel(rl)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RepositoryLabelAPI) getLabels(rType, rID string) {
|
func (r *RepositoryLabelAPI) getLabels(rType string, rIDOrName interface{}) {
|
||||||
labels, err := dao.GetLabelsOfResource(rType, rID)
|
labels, err := dao.GetLabelsOfResource(rType, rIDOrName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.HandleInternalServerError(fmt.Sprintf("failed to get labels of resource %s %s: %v",
|
r.HandleInternalServerError(fmt.Sprintf("failed to get labels of resource %s %v: %v",
|
||||||
rType, rID, err))
|
rType, rIDOrName, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r.Data["json"] = labels
|
r.Data["json"] = labels
|
||||||
@ -196,10 +187,16 @@ func (r *RepositoryLabelAPI) getLabels(rType, rID string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *RepositoryLabelAPI) addLabel(rl *models.ResourceLabel) {
|
func (r *RepositoryLabelAPI) addLabel(rl *models.ResourceLabel) {
|
||||||
rlabel, err := dao.GetResourceLabel(rl.ResourceType, rl.ResourceID, rl.LabelID)
|
var rIDOrName interface{}
|
||||||
|
if rl.ResourceID != 0 {
|
||||||
|
rIDOrName = rl.ResourceID
|
||||||
|
} else {
|
||||||
|
rIDOrName = rl.ResourceName
|
||||||
|
}
|
||||||
|
rlabel, err := dao.GetResourceLabel(rl.ResourceType, rIDOrName, rl.LabelID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.HandleInternalServerError(fmt.Sprintf("failed to check the existence of label %d for resource %s %s: %v",
|
r.HandleInternalServerError(fmt.Sprintf("failed to check the existence of label %d for resource %s %v: %v",
|
||||||
rl.LabelID, rl.ResourceType, rl.ResourceID, err))
|
rl.LabelID, rl.ResourceType, rIDOrName, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,8 +205,8 @@ func (r *RepositoryLabelAPI) addLabel(rl *models.ResourceLabel) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err := dao.AddResourceLabel(rl); err != nil {
|
if _, err := dao.AddResourceLabel(rl); err != nil {
|
||||||
r.HandleInternalServerError(fmt.Sprintf("failed to add label %d to resource %s %s: %v",
|
r.HandleInternalServerError(fmt.Sprintf("failed to add label %d to resource %s %v: %v",
|
||||||
rl.LabelID, rl.ResourceType, rl.ResourceID, err))
|
rl.LabelID, rl.ResourceType, rIDOrName, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,22 +214,22 @@ func (r *RepositoryLabelAPI) addLabel(rl *models.ResourceLabel) {
|
|||||||
r.Redirect(http.StatusOK, strconv.FormatInt(rl.LabelID, 10))
|
r.Redirect(http.StatusOK, strconv.FormatInt(rl.LabelID, 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RepositoryLabelAPI) removeLabel(rl *models.ResourceLabel) {
|
func (r *RepositoryLabelAPI) removeLabel(rType string, rIDOrName interface{}, labelID int64) {
|
||||||
rlabel, err := dao.GetResourceLabel(rl.ResourceType, rl.ResourceID, rl.LabelID)
|
rl, err := dao.GetResourceLabel(rType, rIDOrName, labelID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.HandleInternalServerError(fmt.Sprintf("failed to check the existence of label %d for resource %s %s: %v",
|
r.HandleInternalServerError(fmt.Sprintf("failed to check the existence of label %d for resource %s %v: %v",
|
||||||
rl.LabelID, rl.ResourceType, rl.ResourceID, err))
|
labelID, rType, rIDOrName, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if rlabel == nil {
|
if rl == nil {
|
||||||
r.HandleNotFound(fmt.Sprintf("label %d of resource %s %s not found",
|
r.HandleNotFound(fmt.Sprintf("label %d of resource %s %s not found",
|
||||||
rl.LabelID, rl.ResourceType, rl.ResourceID))
|
labelID, rType, rIDOrName))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = dao.DeleteResourceLabel(rlabel.ID); err != nil {
|
if err = dao.DeleteResourceLabel(rl.ID); err != nil {
|
||||||
r.HandleInternalServerError(fmt.Sprintf("failed to delete resource label record %d: %v",
|
r.HandleInternalServerError(fmt.Sprintf("failed to delete resource label record %d: %v",
|
||||||
rlabel.ID, err))
|
rl.ID, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ func TestGetRepos(t *testing.T) {
|
|||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
apiTest := newHarborAPI()
|
apiTest := newHarborAPI()
|
||||||
projectID := "1"
|
projectID := "1"
|
||||||
keyword := "hello-world"
|
keyword := "library/hello-world"
|
||||||
|
|
||||||
fmt.Println("Testing Repos Get API")
|
fmt.Println("Testing Repos Get API")
|
||||||
//-------------------case 1 : response code = 200------------------------//
|
//-------------------case 1 : response code = 200------------------------//
|
||||||
|
@ -99,13 +99,15 @@ func (s *SearchAPI) Get() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
repos, err := dao.GetRepositoryByProjectName(p.Name)
|
total, err := dao.GetTotalOfRepositories(&models.RepositoryQuery{
|
||||||
|
ProjectIDs: []int64{p.ProjectID},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed to get repositories of project %s: %v", p.Name, err)
|
log.Errorf("failed to get total of repositories of project %d: %v", p.ProjectID, err)
|
||||||
s.CustomAbort(http.StatusInternalServerError, "")
|
s.CustomAbort(http.StatusInternalServerError, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
p.RepoCount = len(repos)
|
p.RepoCount = total
|
||||||
|
|
||||||
projectResult = append(projectResult, p)
|
projectResult = append(projectResult, p)
|
||||||
}
|
}
|
||||||
@ -124,7 +126,7 @@ func (s *SearchAPI) Get() {
|
|||||||
func filterRepositories(projects []*models.Project, keyword string) (
|
func filterRepositories(projects []*models.Project, keyword string) (
|
||||||
[]map[string]interface{}, error) {
|
[]map[string]interface{}, error) {
|
||||||
|
|
||||||
repositories, err := dao.GetAllRepositories()
|
repositories, err := dao.GetRepositories()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -64,17 +64,22 @@ func (s *StatisticAPI) Get() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
statistic[PubPC] = (int64)(len(pubProjs))
|
statistic[PubPC] = (int64)(len(pubProjs))
|
||||||
|
if len(pubProjs) == 0 {
|
||||||
ids := []int64{}
|
statistic[PubRC] = 0
|
||||||
for _, p := range pubProjs {
|
} else {
|
||||||
ids = append(ids, p.ProjectID)
|
ids := []int64{}
|
||||||
|
for _, p := range pubProjs {
|
||||||
|
ids = append(ids, p.ProjectID)
|
||||||
|
}
|
||||||
|
n, err := dao.GetTotalOfRepositories(&models.RepositoryQuery{
|
||||||
|
ProjectIDs: ids,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to get total of public repositories: %v", err)
|
||||||
|
s.CustomAbort(http.StatusInternalServerError, "")
|
||||||
|
}
|
||||||
|
statistic[PubRC] = n
|
||||||
}
|
}
|
||||||
n, err := dao.GetTotalOfRepositoriesByProject(ids, "")
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed to get total of public repositories: %v", err)
|
|
||||||
s.CustomAbort(http.StatusInternalServerError, "")
|
|
||||||
}
|
|
||||||
statistic[PubRC] = n
|
|
||||||
|
|
||||||
if s.SecurityCtx.IsSysAdmin() {
|
if s.SecurityCtx.IsSysAdmin() {
|
||||||
result, err := s.ProjectMgr.List(nil)
|
result, err := s.ProjectMgr.List(nil)
|
||||||
@ -85,7 +90,7 @@ func (s *StatisticAPI) Get() {
|
|||||||
statistic[TPC] = result.Total
|
statistic[TPC] = result.Total
|
||||||
statistic[PriPC] = result.Total - statistic[PubPC]
|
statistic[PriPC] = result.Total - statistic[PubPC]
|
||||||
|
|
||||||
n, err := dao.GetTotalOfRepositories("")
|
n, err := dao.GetTotalOfRepositories()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed to get total of repositories: %v", err)
|
log.Errorf("failed to get total of repositories: %v", err)
|
||||||
s.CustomAbort(http.StatusInternalServerError, "")
|
s.CustomAbort(http.StatusInternalServerError, "")
|
||||||
@ -107,20 +112,25 @@ func (s *StatisticAPI) Get() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
statistic[PriPC] = result.Total
|
statistic[PriPC] = result.Total
|
||||||
|
if result.Total == 0 {
|
||||||
|
statistic[PriRC] = 0
|
||||||
|
} else {
|
||||||
|
ids := []int64{}
|
||||||
|
for _, p := range result.Projects {
|
||||||
|
ids = append(ids, p.ProjectID)
|
||||||
|
}
|
||||||
|
|
||||||
ids := []int64{}
|
n, err := dao.GetTotalOfRepositories(&models.RepositoryQuery{
|
||||||
for _, p := range result.Projects {
|
ProjectIDs: ids,
|
||||||
ids = append(ids, p.ProjectID)
|
})
|
||||||
|
if err != nil {
|
||||||
|
s.HandleInternalServerError(fmt.Sprintf(
|
||||||
|
"failed to get total of repositories for user %s: %v",
|
||||||
|
s.username, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
statistic[PriRC] = n
|
||||||
}
|
}
|
||||||
|
|
||||||
n, err = dao.GetTotalOfRepositoriesByProject(ids, "")
|
|
||||||
if err != nil {
|
|
||||||
s.HandleInternalServerError(fmt.Sprintf(
|
|
||||||
"failed to get total of repositories for user %s: %v",
|
|
||||||
s.username, err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
statistic[PriRC] = n
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Data["json"] = statistic
|
s.Data["json"] = statistic
|
||||||
|
@ -86,7 +86,7 @@ func SyncRegistry(pm promgr.ProjectManager) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var repoRecordsInDB []*models.RepoRecord
|
var repoRecordsInDB []*models.RepoRecord
|
||||||
repoRecordsInDB, err = dao.GetAllRepositories()
|
repoRecordsInDB, err = dao.GetRepositories()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("error occurred while getting all registories. %v", err)
|
log.Errorf("error occurred while getting all registories. %v", err)
|
||||||
return err
|
return err
|
||||||
|
@ -33,7 +33,7 @@ import (
|
|||||||
|
|
||||||
// ScanAllImages scans all images of Harbor by submiting jobs to jobservice, the whole process will move on if failed to submit any job of a single image.
|
// ScanAllImages scans all images of Harbor by submiting jobs to jobservice, the whole process will move on if failed to submit any job of a single image.
|
||||||
func ScanAllImages() error {
|
func ScanAllImages() error {
|
||||||
repos, err := dao.GetAllRepositories()
|
repos, err := dao.GetRepositories()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Failed to list all repositories, error: %v", err)
|
log.Errorf("Failed to list all repositories, error: %v", err)
|
||||||
return err
|
return err
|
||||||
@ -46,7 +46,9 @@ func ScanAllImages() error {
|
|||||||
|
|
||||||
// ScanImagesByProjectID scans all images under a projet, the whole process will move on if failed to submit any job of a single image.
|
// ScanImagesByProjectID scans all images under a projet, the whole process will move on if failed to submit any job of a single image.
|
||||||
func ScanImagesByProjectID(id int64) error {
|
func ScanImagesByProjectID(id int64) error {
|
||||||
repos, err := dao.GetRepositoriesByProject(id, "", 0, 0)
|
repos, err := dao.GetRepositories(&models.RepositoryQuery{
|
||||||
|
ProjectIDs: []int64{id},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Failed list repositories in project %d, error: %v", id, err)
|
log.Errorf("Failed list repositories in project %d, error: %v", id, err)
|
||||||
return err
|
return err
|
||||||
|
Loading…
Reference in New Issue
Block a user