mirror of
https://github.com/goharbor/harbor.git
synced 2024-09-26 04:23:22 +02:00
update blob list query (#14195)
* update blob list query Deprecate blob list parameters, and use the query for instead. Signed-off-by: wang yan <wangyan@vmware.com> * update per review comments Signed-off-by: Wang Yan <wangyan@vmware.com>
This commit is contained in:
parent
7231679373
commit
21d35f9702
@ -18,6 +18,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/goharbor/harbor/src/lib/q"
|
||||
|
||||
"github.com/docker/distribution/manifest/manifestlist"
|
||||
"github.com/docker/distribution/manifest/schema1"
|
||||
@ -95,13 +96,13 @@ func (a *abstractor) abstractManifestV1Metadata(ctx context.Context, artifact *a
|
||||
return err
|
||||
}
|
||||
|
||||
digests := make([]string, len(manifest.FSLayers))
|
||||
for i, fsLayer := range manifest.FSLayers {
|
||||
digests[i] = fsLayer.BlobSum.String()
|
||||
var ol q.OrList
|
||||
for _, fsLayer := range manifest.FSLayers {
|
||||
ol.Values = append(ol.Values, fsLayer.BlobSum.String())
|
||||
}
|
||||
|
||||
// there is no layer size in v1 manifest, compute the artifact size from the blobs
|
||||
blobs, err := a.blobMgr.List(ctx, blob.ListParams{BlobDigests: digests})
|
||||
blobs, err := a.blobMgr.List(ctx, q.New(q.KeyWords{"digest": &ol}))
|
||||
if err != nil {
|
||||
log.G(ctx).Errorf("failed to get blobs of the artifact %s, error %v", artifact.Digest, err)
|
||||
return err
|
||||
|
@ -356,7 +356,7 @@ func (c *controller) deleteDeeply(ctx context.Context, id int64, isRoot bool) er
|
||||
return err
|
||||
}
|
||||
|
||||
blobs, err := c.blobMgr.List(ctx, blob.ListParams{ArtifactDigest: art.Digest})
|
||||
blobs, err := c.blobMgr.List(ctx, q.New(q.KeyWords{"artifactDigest": art.Digest}))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ package blob
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/goharbor/harbor/src/lib/q"
|
||||
"time"
|
||||
|
||||
"github.com/docker/distribution"
|
||||
@ -65,7 +66,7 @@ type Controller interface {
|
||||
Get(ctx context.Context, digest string, options ...Option) (*blob.Blob, error)
|
||||
|
||||
// List list blobs
|
||||
List(ctx context.Context, params blob.ListParams) ([]*blob.Blob, error)
|
||||
List(ctx context.Context, query *q.Query) ([]*blob.Blob, error)
|
||||
|
||||
// Sync create blobs from `References` when they are not exist
|
||||
// and update the blob content type when they are exist,
|
||||
@ -178,12 +179,12 @@ func (c *controller) FindMissingAssociationsForProject(ctx context.Context, proj
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var digests []string
|
||||
var ol q.OrList
|
||||
for _, blob := range blobs {
|
||||
digests = append(digests, blob.Digest)
|
||||
ol.Values = append(ol.Values, blob.Digest)
|
||||
}
|
||||
|
||||
associatedBlobs, err := c.blobMgr.List(ctx, blob.ListParams{BlobDigests: digests, ProjectID: projectID})
|
||||
associatedBlobs, err := c.blobMgr.List(ctx, q.New(q.KeyWords{"digest": &ol, "projectID": projectID}))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -216,13 +217,26 @@ func (c *controller) Get(ctx context.Context, digest string, options ...Option)
|
||||
|
||||
opts := newOptions(options...)
|
||||
|
||||
params := blob.ListParams{
|
||||
ArtifactDigest: opts.ArtifactDigest,
|
||||
BlobDigests: []string{digest},
|
||||
ProjectID: opts.ProjectID,
|
||||
keywords := make(map[string]interface{})
|
||||
if digest != "" {
|
||||
ol := q.OrList{
|
||||
Values: []interface{}{
|
||||
digest,
|
||||
},
|
||||
}
|
||||
keywords["digest"] = &ol
|
||||
}
|
||||
if opts.ProjectID != 0 {
|
||||
keywords["projectID"] = opts.ProjectID
|
||||
}
|
||||
if opts.ArtifactDigest != "" {
|
||||
keywords["artifactDigest"] = opts.ArtifactDigest
|
||||
}
|
||||
query := &q.Query{
|
||||
Keywords: keywords,
|
||||
}
|
||||
|
||||
blobs, err := c.blobMgr.List(ctx, params)
|
||||
blobs, err := c.blobMgr.List(ctx, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if len(blobs) == 0 {
|
||||
@ -232,8 +246,8 @@ func (c *controller) Get(ctx context.Context, digest string, options ...Option)
|
||||
return blobs[0], nil
|
||||
}
|
||||
|
||||
func (c *controller) List(ctx context.Context, params blob.ListParams) ([]*blob.Blob, error) {
|
||||
return c.blobMgr.List(ctx, params)
|
||||
func (c *controller) List(ctx context.Context, query *q.Query) ([]*blob.Blob, error) {
|
||||
return c.blobMgr.List(ctx, query)
|
||||
}
|
||||
|
||||
func (c *controller) Sync(ctx context.Context, references []distribution.Descriptor) error {
|
||||
@ -241,12 +255,12 @@ func (c *controller) Sync(ctx context.Context, references []distribution.Descrip
|
||||
return nil
|
||||
}
|
||||
|
||||
var digests []string
|
||||
var ol q.OrList
|
||||
for _, reference := range references {
|
||||
digests = append(digests, reference.Digest.String())
|
||||
ol.Values = append(ol.Values, reference.Digest.String())
|
||||
}
|
||||
|
||||
blobs, err := c.blobMgr.List(ctx, blob.ListParams{BlobDigests: digests})
|
||||
blobs, err := c.blobMgr.List(ctx, q.New(q.KeyWords{"digest": &ol}))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -423,17 +423,40 @@ func (gc *GarbageCollector) removeUntaggedBlobs(ctx job.Context) {
|
||||
continue
|
||||
}
|
||||
p := result.Data
|
||||
all, err := gc.blobMgr.List(ctx.SystemContext(), blob.ListParams{
|
||||
ProjectID: p.ProjectID,
|
||||
UpdateTime: time.Now().Add(-time.Duration(gc.timeWindowHours) * time.Hour),
|
||||
})
|
||||
if err != nil {
|
||||
gc.logger.Errorf("failed to get blobs of project, %v", err)
|
||||
continue
|
||||
|
||||
ps := 1000
|
||||
lastBlobID := int64(0)
|
||||
timeRG := q.Range{
|
||||
Max: time.Now().Add(-time.Duration(gc.timeWindowHours) * time.Hour).Format(time.RFC3339),
|
||||
}
|
||||
if err := gc.blobMgr.CleanupAssociationsForProject(ctx.SystemContext(), p.ProjectID, all); err != nil {
|
||||
gc.logger.Errorf("failed to clean untagged blobs of project, %v", err)
|
||||
continue
|
||||
|
||||
for {
|
||||
blobRG := q.Range{
|
||||
Min: lastBlobID,
|
||||
}
|
||||
q := &q.Query{
|
||||
Keywords: map[string]interface{}{
|
||||
"update_time": &timeRG,
|
||||
"projectID": p.ProjectID,
|
||||
"id": &blobRG,
|
||||
},
|
||||
PageNumber: 1,
|
||||
PageSize: int64(ps),
|
||||
Sorting: "id",
|
||||
}
|
||||
blobs, err := gc.blobMgr.List(ctx.SystemContext(), q)
|
||||
if err != nil {
|
||||
gc.logger.Errorf("failed to get blobs of project, %v", err)
|
||||
break
|
||||
}
|
||||
if err := gc.blobMgr.CleanupAssociationsForProject(ctx.SystemContext(), p.ProjectID, blobs); err != nil {
|
||||
gc.logger.Errorf("failed to clean untagged blobs of project, %v", err)
|
||||
break
|
||||
}
|
||||
if len(blobs) < ps {
|
||||
break
|
||||
}
|
||||
lastBlobID = blobs[len(blobs)-1].ID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -288,9 +288,8 @@ func (gc *GarbageCollector) removeUntaggedBlobs(ctx job.Context) {
|
||||
continue
|
||||
}
|
||||
p := result.Data
|
||||
all, err := gc.blobMgr.List(ctx.SystemContext(), blob.ListParams{
|
||||
ProjectID: p.ProjectID,
|
||||
})
|
||||
|
||||
all, err := gc.blobMgr.List(ctx.SystemContext(), q.New(q.KeyWords{"projectID": p.ProjectID}))
|
||||
if err != nil {
|
||||
gc.logger.Errorf("failed to get blobs of project, %v", err)
|
||||
continue
|
||||
|
@ -19,7 +19,6 @@ import (
|
||||
"fmt"
|
||||
"github.com/goharbor/harbor/src/lib/errors"
|
||||
"github.com/goharbor/harbor/src/lib/log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/distribution/manifest/schema2"
|
||||
@ -55,7 +54,7 @@ type DAO interface {
|
||||
UpdateBlobStatus(ctx context.Context, blob *models.Blob) (int64, error)
|
||||
|
||||
// ListBlobs list blobs by query
|
||||
ListBlobs(ctx context.Context, params models.ListParams) ([]*models.Blob, error)
|
||||
ListBlobs(ctx context.Context, query *q.Query) ([]*models.Blob, error)
|
||||
|
||||
// FindBlobsShouldUnassociatedWithProject filter the blobs which should not be associated with the project
|
||||
FindBlobsShouldUnassociatedWithProject(ctx context.Context, projectID int64, blobs []*models.Blob) ([]*models.Blob, error)
|
||||
@ -218,38 +217,12 @@ func (d *dao) UpdateBlob(ctx context.Context, blob *models.Blob) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *dao) ListBlobs(ctx context.Context, params models.ListParams) ([]*models.Blob, error) {
|
||||
qs, err := orm.QuerySetter(ctx, &models.Blob{}, nil)
|
||||
func (d *dao) ListBlobs(ctx context.Context, query *q.Query) ([]*models.Blob, error) {
|
||||
qs, err := orm.QuerySetter(ctx, &models.Blob{}, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(params.BlobDigests) > 0 {
|
||||
qs = qs.Filter("digest__in", params.BlobDigests)
|
||||
}
|
||||
|
||||
if !params.UpdateTime.IsZero() {
|
||||
qs = qs.Filter("update_time__lte", params.UpdateTime)
|
||||
}
|
||||
|
||||
if params.ArtifactDigest != "" {
|
||||
params.ArtifactDigests = append(params.ArtifactDigests, params.ArtifactDigest)
|
||||
}
|
||||
|
||||
if len(params.ArtifactDigests) > 0 {
|
||||
var p []string
|
||||
for _, digest := range params.ArtifactDigests {
|
||||
p = append(p, `'`+orm.Escape(digest)+`'`)
|
||||
}
|
||||
sql := fmt.Sprintf("IN (SELECT digest_blob FROM artifact_blob WHERE digest_af IN (%s))", strings.Join(p, ","))
|
||||
qs = qs.FilterRaw("digest", sql)
|
||||
}
|
||||
|
||||
if params.ProjectID != 0 {
|
||||
sql := fmt.Sprintf("IN (SELECT blob_id FROM project_blob WHERE project_id = %d)", params.ProjectID)
|
||||
qs = qs.FilterRaw("id", sql)
|
||||
}
|
||||
|
||||
blobs := []*models.Blob{}
|
||||
if _, err = qs.All(&blobs); err != nil {
|
||||
return nil, err
|
||||
|
@ -16,6 +16,7 @@ package dao
|
||||
|
||||
import (
|
||||
"github.com/goharbor/harbor/src/lib/errors"
|
||||
"github.com/goharbor/harbor/src/lib/q"
|
||||
"github.com/goharbor/harbor/src/pkg/blob/models"
|
||||
htesting "github.com/goharbor/harbor/src/testing"
|
||||
"github.com/stretchr/testify/suite"
|
||||
@ -202,27 +203,42 @@ func (suite *DaoTestSuite) TestListBlobs() {
|
||||
digest2 := suite.DigestString()
|
||||
suite.dao.CreateBlob(ctx, &models.Blob{Digest: digest2})
|
||||
|
||||
blobs, err := suite.dao.ListBlobs(ctx, models.ListParams{BlobDigests: []string{digest1}})
|
||||
ol := q.OrList{
|
||||
Values: []interface{}{
|
||||
digest1,
|
||||
},
|
||||
}
|
||||
blobs, err := suite.dao.ListBlobs(ctx, q.New(q.KeyWords{"digest": &ol}))
|
||||
if suite.Nil(err) {
|
||||
suite.Len(blobs, 1)
|
||||
}
|
||||
|
||||
blobs, err = suite.dao.ListBlobs(ctx, models.ListParams{BlobDigests: []string{digest1, digest2}})
|
||||
ol = q.OrList{
|
||||
Values: []interface{}{
|
||||
digest1,
|
||||
digest2,
|
||||
},
|
||||
}
|
||||
blobs, err = suite.dao.ListBlobs(ctx, q.New(q.KeyWords{"digest": &ol}))
|
||||
if suite.Nil(err) {
|
||||
suite.Len(blobs, 2)
|
||||
}
|
||||
|
||||
blobs, err = suite.dao.ListBlobs(ctx, models.ListParams{UpdateTime: time.Now().Add(-time.Hour)})
|
||||
rg := q.Range{
|
||||
Max: time.Now().Add(-time.Hour).Format(time.RFC3339),
|
||||
}
|
||||
blobs, err = suite.dao.ListBlobs(ctx, q.New(q.KeyWords{"update_time": &rg}))
|
||||
if suite.Nil(err) {
|
||||
suite.Len(blobs, 0)
|
||||
}
|
||||
|
||||
digest3 := suite.DigestString()
|
||||
suite.dao.CreateBlob(ctx, &models.Blob{Digest: digest3, UpdateTime: time.Now().Add(-time.Hour * 2)})
|
||||
blobs, err = suite.dao.ListBlobs(ctx, models.ListParams{UpdateTime: time.Now().Add(-time.Hour)})
|
||||
blobs, err = suite.dao.ListBlobs(ctx, q.New(q.KeyWords{"update_time": &rg}))
|
||||
if suite.Nil(err) {
|
||||
suite.Len(blobs, 1)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (suite *DaoTestSuite) TestListBlobsAssociatedWithArtifact() {
|
||||
@ -248,15 +264,17 @@ func (suite *DaoTestSuite) TestFindBlobsShouldUnassociatedWithProject() {
|
||||
digest4 := suite.DigestString()
|
||||
digest5 := suite.DigestString()
|
||||
|
||||
var ol q.OrList
|
||||
blobDigests := []string{digest1, digest2, digest3, digest4, digest5}
|
||||
for _, digest := range blobDigests {
|
||||
blobID, err := suite.dao.CreateBlob(ctx, &models.Blob{Digest: digest})
|
||||
if suite.Nil(err) {
|
||||
suite.dao.CreateProjectBlob(ctx, projectID, blobID)
|
||||
}
|
||||
ol.Values = append(ol.Values, digest)
|
||||
}
|
||||
|
||||
blobs, err := suite.dao.ListBlobs(ctx, models.ListParams{BlobDigests: blobDigests})
|
||||
blobs, err := suite.dao.ListBlobs(ctx, q.New(q.KeyWords{"digest": &ol}))
|
||||
suite.Nil(err)
|
||||
suite.Len(blobs, 5)
|
||||
|
||||
|
@ -17,6 +17,7 @@ package blob
|
||||
import (
|
||||
"context"
|
||||
"github.com/goharbor/harbor/src/lib/errors"
|
||||
"github.com/goharbor/harbor/src/lib/q"
|
||||
"github.com/goharbor/harbor/src/pkg/blob/dao"
|
||||
"github.com/goharbor/harbor/src/pkg/blob/models"
|
||||
)
|
||||
@ -24,9 +25,6 @@ import (
|
||||
// Blob alias `models.Blob` to make it natural to use the Manager
|
||||
type Blob = models.Blob
|
||||
|
||||
// ListParams alias `models.ListParams` to make it natural to use the Manager
|
||||
type ListParams = models.ListParams
|
||||
|
||||
var (
|
||||
// Mgr default blob manager
|
||||
Mgr = NewManager()
|
||||
@ -62,7 +60,7 @@ type Manager interface {
|
||||
UpdateBlobStatus(ctx context.Context, blob *models.Blob) (int64, error)
|
||||
|
||||
// List returns blobs by params
|
||||
List(ctx context.Context, params ListParams) ([]*Blob, error)
|
||||
List(ctx context.Context, query *q.Query) ([]*Blob, error)
|
||||
|
||||
// DeleteBlob delete blob
|
||||
Delete(ctx context.Context, id int64) (err error)
|
||||
@ -129,8 +127,8 @@ func (m *manager) UpdateBlobStatus(ctx context.Context, blob *models.Blob) (int6
|
||||
return m.dao.UpdateBlobStatus(ctx, blob)
|
||||
}
|
||||
|
||||
func (m *manager) List(ctx context.Context, params ListParams) ([]*Blob, error) {
|
||||
return m.dao.ListBlobs(ctx, params)
|
||||
func (m *manager) List(ctx context.Context, query *q.Query) ([]*Blob, error) {
|
||||
return m.dao.ListBlobs(ctx, query)
|
||||
}
|
||||
|
||||
func (m *manager) Delete(ctx context.Context, id int64) error {
|
||||
|
@ -16,6 +16,7 @@ package blob
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/goharbor/harbor/src/lib/q"
|
||||
htesting "github.com/goharbor/harbor/src/testing"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"testing"
|
||||
@ -34,7 +35,12 @@ func (suite *ManagerTestSuite) SetupSuite() {
|
||||
}
|
||||
|
||||
func (suite *ManagerTestSuite) isAssociatedWithArtifact(ctx context.Context, blobDigest, artifactDigest string) (bool, error) {
|
||||
blobs, err := Mgr.List(ctx, ListParams{BlobDigests: []string{blobDigest}, ArtifactDigest: artifactDigest})
|
||||
ol := q.OrList{
|
||||
Values: []interface{}{
|
||||
blobDigest,
|
||||
},
|
||||
}
|
||||
blobs, err := Mgr.List(ctx, q.New(q.KeyWords{"digest": &ol, "artifactDigest": artifactDigest}))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -43,7 +49,12 @@ func (suite *ManagerTestSuite) isAssociatedWithArtifact(ctx context.Context, blo
|
||||
}
|
||||
|
||||
func (suite *ManagerTestSuite) isAssociatedWithProject(ctx context.Context, blobDigest string, projectID int64) (bool, error) {
|
||||
blobs, err := Mgr.List(ctx, ListParams{BlobDigests: []string{blobDigest}, ProjectID: projectID})
|
||||
ol := q.OrList{
|
||||
Values: []interface{}{
|
||||
blobDigest,
|
||||
},
|
||||
}
|
||||
blobs, err := Mgr.List(ctx, q.New(q.KeyWords{"digest": &ol, "projectID": projectID}))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -117,14 +128,15 @@ func (suite *ManagerTestSuite) TestCleanupAssociationsForProject() {
|
||||
ctx := suite.Context()
|
||||
|
||||
blobDigests := []string{digest1, digest2, digest3, digest4, digest5}
|
||||
var ol q.OrList
|
||||
for _, digest := range blobDigests {
|
||||
blobID, err := Mgr.Create(ctx, digest, "media type", 100)
|
||||
if suite.Nil(err) {
|
||||
Mgr.AssociateWithProject(ctx, blobID, projectID)
|
||||
}
|
||||
ol.Values = append(ol.Values, digest)
|
||||
}
|
||||
|
||||
blobs, err := Mgr.List(ctx, ListParams{BlobDigests: blobDigests})
|
||||
blobs, err := Mgr.List(ctx, q.New(q.KeyWords{"digest": &ol}))
|
||||
suite.Nil(err)
|
||||
suite.Len(blobs, 5)
|
||||
|
||||
@ -213,18 +225,33 @@ func (suite *ManagerTestSuite) TestList() {
|
||||
digest1 := suite.DigestString()
|
||||
digest2 := suite.DigestString()
|
||||
|
||||
blobs, err := Mgr.List(ctx, ListParams{BlobDigests: []string{digest1, digest2}})
|
||||
ol := q.OrList{
|
||||
Values: []interface{}{
|
||||
digest1,
|
||||
digest2,
|
||||
},
|
||||
}
|
||||
blobs, err := Mgr.List(ctx, q.New(q.KeyWords{"digest": &ol}))
|
||||
suite.Nil(err)
|
||||
suite.Len(blobs, 0)
|
||||
|
||||
Mgr.Create(ctx, digest1, "media type", 100)
|
||||
Mgr.Create(ctx, digest2, "media type", 100)
|
||||
|
||||
blobs, err = Mgr.List(ctx, ListParams{BlobDigests: []string{digest1, digest2}})
|
||||
ol = q.OrList{
|
||||
Values: []interface{}{
|
||||
digest1,
|
||||
digest2,
|
||||
},
|
||||
}
|
||||
blobs, err = Mgr.List(ctx, q.New(q.KeyWords{"digest": &ol}))
|
||||
suite.Nil(err)
|
||||
suite.Len(blobs, 2)
|
||||
|
||||
blobs, err = Mgr.List(ctx, models.ListParams{UpdateTime: time.Now().Add(-time.Hour)})
|
||||
rg := q.Range{
|
||||
Max: time.Now().Add(-time.Hour).Format(time.RFC3339),
|
||||
}
|
||||
blobs, err = Mgr.List(ctx, q.New(q.KeyWords{"update_time": &rg}))
|
||||
if suite.Nil(err) {
|
||||
suite.Len(blobs, 0)
|
||||
}
|
||||
@ -255,11 +282,11 @@ func (suite *ManagerTestSuite) TestListByArtifact() {
|
||||
}
|
||||
}
|
||||
|
||||
blobs, err := Mgr.List(ctx, ListParams{ArtifactDigest: artifact1})
|
||||
blobs, err := Mgr.List(ctx, q.New(q.KeyWords{"artifactDigest": artifact1}))
|
||||
suite.Nil(err)
|
||||
suite.Len(blobs, 5)
|
||||
|
||||
blobs, err = Mgr.List(ctx, ListParams{ArtifactDigest: artifact2})
|
||||
blobs, err = Mgr.List(ctx, q.New(q.KeyWords{"artifactDigest": artifact2}))
|
||||
suite.Nil(err)
|
||||
suite.Len(blobs, 3)
|
||||
}
|
||||
|
@ -15,12 +15,15 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/astaxie/beego/orm"
|
||||
"github.com/docker/distribution/manifest/manifestlist"
|
||||
"github.com/docker/distribution/manifest/schema1"
|
||||
"github.com/docker/distribution/manifest/schema2"
|
||||
"github.com/goharbor/harbor/src/common/models"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -99,11 +102,37 @@ func (b *Blob) IsManifest() bool {
|
||||
// ProjectBlob alias ProjectBlob model
|
||||
type ProjectBlob = models.ProjectBlob
|
||||
|
||||
// ListParams list params
|
||||
type ListParams struct {
|
||||
ArtifactDigest string // list blobs which associated with the artifact
|
||||
ArtifactDigests []string // list blobs which associated with these artifacts
|
||||
BlobDigests []string // list blobs which digest in the digests
|
||||
ProjectID int64 // list blobs which associated with the project
|
||||
UpdateTime time.Time // list blobs which update time less than updatetime
|
||||
// FilterByArtifactDigest returns orm.QuerySeter with artifact digest filter
|
||||
func (b *Blob) FilterByArtifactDigest(ctx context.Context, qs orm.QuerySeter, key string, value interface{}) orm.QuerySeter {
|
||||
v, ok := value.(string)
|
||||
if !ok {
|
||||
return qs
|
||||
}
|
||||
sql := fmt.Sprintf("IN (SELECT digest_blob FROM artifact_blob WHERE digest_af IN (%s))", `'`+v+`'`)
|
||||
return qs.FilterRaw("digest", sql)
|
||||
}
|
||||
|
||||
// FilterByArtifactDigests returns orm.QuerySeter with artifact digests filter
|
||||
func (b *Blob) FilterByArtifactDigests(ctx context.Context, qs orm.QuerySeter, key string, value interface{}) orm.QuerySeter {
|
||||
artifactDigests, ok := value.([]string)
|
||||
if !ok {
|
||||
return qs
|
||||
}
|
||||
var afs []string
|
||||
for _, v := range artifactDigests {
|
||||
afs = append(afs, `'`+v+`'`)
|
||||
}
|
||||
|
||||
sql := fmt.Sprintf("IN (SELECT digest_blob FROM artifact_blob WHERE digest_af IN (%s))", strings.Join(afs, ","))
|
||||
return qs.FilterRaw("digest", sql)
|
||||
}
|
||||
|
||||
// FilterByProjectID returns orm.QuerySeter with project id filter
|
||||
func (b *Blob) FilterByProjectID(ctx context.Context, qs orm.QuerySeter, key string, value interface{}) orm.QuerySeter {
|
||||
projectID, ok := value.(int64)
|
||||
if !ok {
|
||||
return qs
|
||||
}
|
||||
|
||||
return qs.FilterRaw("id", fmt.Sprintf("IN (SELECT blob_id FROM project_blob WHERE project_id = %d)", projectID))
|
||||
}
|
||||
|
@ -29,13 +29,13 @@
|
||||
package blob
|
||||
|
||||
import (
|
||||
"github.com/goharbor/harbor/src/lib/q"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/goharbor/harbor/src/controller/artifact"
|
||||
"github.com/goharbor/harbor/src/lib/errors"
|
||||
"github.com/goharbor/harbor/src/lib/log"
|
||||
"github.com/goharbor/harbor/src/pkg/blob"
|
||||
"github.com/goharbor/harbor/src/pkg/distribution"
|
||||
"github.com/goharbor/harbor/src/server/middleware"
|
||||
"github.com/goharbor/harbor/src/server/middleware/util"
|
||||
@ -91,7 +91,7 @@ func CopyArtifactMiddleware() func(http.Handler) http.Handler {
|
||||
return err
|
||||
}
|
||||
|
||||
allBlobs, err := blobController.List(ctx, blob.ListParams{ArtifactDigests: artifactDigests})
|
||||
allBlobs, err := blobController.List(ctx, q.New(q.KeyWords{"artifactDigests": artifactDigests}))
|
||||
if err != nil {
|
||||
logger.Errorf("get blobs for artifacts %s failed, error: %v", strings.Join(artifactDigests, ", "), err)
|
||||
return err
|
||||
|
@ -29,6 +29,7 @@
|
||||
package quota
|
||||
|
||||
import (
|
||||
"github.com/goharbor/harbor/src/lib/q"
|
||||
"net/http"
|
||||
"path"
|
||||
"strconv"
|
||||
@ -39,7 +40,6 @@ import (
|
||||
"github.com/goharbor/harbor/src/controller/event/metadata"
|
||||
"github.com/goharbor/harbor/src/lib/errors"
|
||||
"github.com/goharbor/harbor/src/lib/log"
|
||||
"github.com/goharbor/harbor/src/pkg/blob"
|
||||
"github.com/goharbor/harbor/src/pkg/distribution"
|
||||
"github.com/goharbor/harbor/src/pkg/notifier/event"
|
||||
"github.com/goharbor/harbor/src/pkg/quota/types"
|
||||
@ -109,7 +109,7 @@ func copyArtifactResources(r *http.Request, reference, referenceID string) (type
|
||||
return nil, err
|
||||
}
|
||||
|
||||
allBlobs, err := blobController.List(ctx, blob.ListParams{ArtifactDigests: artifactDigests})
|
||||
allBlobs, err := blobController.List(ctx, q.New(q.KeyWords{"artifactDigests": artifactDigests}))
|
||||
if err != nil {
|
||||
logger.Errorf("get blobs for artifacts %s failed, error: %v", strings.Join(artifactDigests, ", "), err)
|
||||
return nil, err
|
||||
|
@ -12,6 +12,8 @@ import (
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
models "github.com/goharbor/harbor/src/pkg/blob/models"
|
||||
|
||||
q "github.com/goharbor/harbor/src/lib/q"
|
||||
)
|
||||
|
||||
// Controller is an autogenerated mock type for the Controller type
|
||||
@ -233,13 +235,13 @@ func (_m *Controller) GetAcceptedBlobSize(sessionID string) (int64, error) {
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// List provides a mock function with given fields: ctx, params
|
||||
func (_m *Controller) List(ctx context.Context, params models.ListParams) ([]*models.Blob, error) {
|
||||
ret := _m.Called(ctx, params)
|
||||
// List provides a mock function with given fields: ctx, query
|
||||
func (_m *Controller) List(ctx context.Context, query *q.Query) ([]*models.Blob, error) {
|
||||
ret := _m.Called(ctx, query)
|
||||
|
||||
var r0 []*models.Blob
|
||||
if rf, ok := ret.Get(0).(func(context.Context, models.ListParams) []*models.Blob); ok {
|
||||
r0 = rf(ctx, params)
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *q.Query) []*models.Blob); ok {
|
||||
r0 = rf(ctx, query)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*models.Blob)
|
||||
@ -247,8 +249,8 @@ func (_m *Controller) List(ctx context.Context, params models.ListParams) ([]*mo
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, models.ListParams) error); ok {
|
||||
r1 = rf(ctx, params)
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *q.Query) error); ok {
|
||||
r1 = rf(ctx, query)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ import (
|
||||
|
||||
models "github.com/goharbor/harbor/src/pkg/blob/models"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
q "github.com/goharbor/harbor/src/lib/q"
|
||||
)
|
||||
|
||||
// Manager is an autogenerated mock type for the Manager type
|
||||
@ -163,13 +165,13 @@ func (_m *Manager) Get(ctx context.Context, digest string) (*models.Blob, error)
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// List provides a mock function with given fields: ctx, params
|
||||
func (_m *Manager) List(ctx context.Context, params models.ListParams) ([]*models.Blob, error) {
|
||||
ret := _m.Called(ctx, params)
|
||||
// List provides a mock function with given fields: ctx, query
|
||||
func (_m *Manager) List(ctx context.Context, query *q.Query) ([]*models.Blob, error) {
|
||||
ret := _m.Called(ctx, query)
|
||||
|
||||
var r0 []*models.Blob
|
||||
if rf, ok := ret.Get(0).(func(context.Context, models.ListParams) []*models.Blob); ok {
|
||||
r0 = rf(ctx, params)
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *q.Query) []*models.Blob); ok {
|
||||
r0 = rf(ctx, query)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*models.Blob)
|
||||
@ -177,8 +179,8 @@ func (_m *Manager) List(ctx context.Context, params models.ListParams) ([]*model
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, models.ListParams) error); ok {
|
||||
r1 = rf(ctx, params)
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *q.Query) error); ok {
|
||||
r1 = rf(ctx, query)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user