mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-20 23:57:42 +01:00
add get GC candidate (#12314)
* add get GC candidate select non referenced blobs from table blob and exclude the ones in the time windows. Signed-off-by: wang yan <wangyan@vmware.com>
This commit is contained in:
parent
9cff87cd52
commit
57c72b7952
@ -75,6 +75,9 @@ type DAO interface {
|
|||||||
|
|
||||||
// DeleteBlob delete blob
|
// DeleteBlob delete blob
|
||||||
DeleteBlob(ctx context.Context, id int64) (err error)
|
DeleteBlob(ctx context.Context, id int64) (err error)
|
||||||
|
|
||||||
|
// GetBlobsNotRefedByProjectBlob get the blobs that are not referenced by the table project_blob and also not in the reserve window(in hours)
|
||||||
|
GetBlobsNotRefedByProjectBlob(ctx context.Context, timeWindowHours int64) ([]*models.Blob, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns an instance of the default DAO
|
// New returns an instance of the default DAO
|
||||||
@ -389,3 +392,19 @@ func (d *dao) DeleteBlob(ctx context.Context, id int64) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *dao) GetBlobsNotRefedByProjectBlob(ctx context.Context, timeWindowHours int64) ([]*models.Blob, error) {
|
||||||
|
var noneRefed []*models.Blob
|
||||||
|
ormer, err := orm.FromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return noneRefed, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sql := fmt.Sprintf(`SELECT b.id, b.digest, b.content_type, b.status FROM blob AS b LEFT JOIN project_blob pb ON b.id = pb.blob_id WHERE pb.id IS NULL AND b.update_time <= now() - interval '%d hours';`, timeWindowHours)
|
||||||
|
_, err = ormer.Raw(sql).QueryRows(&noneRefed)
|
||||||
|
if err != nil {
|
||||||
|
return noneRefed, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return noneRefed, nil
|
||||||
|
}
|
||||||
|
@ -376,6 +376,34 @@ func (suite *DaoTestSuite) TestDelete() {
|
|||||||
suite.Require().Nil(err)
|
suite.Require().Nil(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *DaoTestSuite) TestGetBlobsNotRefedByProjectBlob() {
|
||||||
|
ctx := suite.Context()
|
||||||
|
|
||||||
|
blobs, err := suite.dao.GetBlobsNotRefedByProjectBlob(ctx, 0)
|
||||||
|
suite.Require().Nil(err)
|
||||||
|
beforeAdd := len(blobs)
|
||||||
|
|
||||||
|
suite.dao.CreateBlob(ctx, &models.Blob{Digest: suite.DigestString()})
|
||||||
|
suite.dao.CreateBlob(ctx, &models.Blob{Digest: suite.DigestString()})
|
||||||
|
digest := suite.DigestString()
|
||||||
|
suite.dao.CreateBlob(ctx, &models.Blob{Digest: digest})
|
||||||
|
|
||||||
|
blob, err := suite.dao.GetBlobByDigest(ctx, digest)
|
||||||
|
suite.Nil(err)
|
||||||
|
|
||||||
|
projectID := int64(1)
|
||||||
|
_, err = suite.dao.CreateProjectBlob(ctx, projectID, blob.ID)
|
||||||
|
suite.Nil(err)
|
||||||
|
|
||||||
|
blobs, err = suite.dao.GetBlobsNotRefedByProjectBlob(ctx, 0)
|
||||||
|
suite.Require().Nil(err)
|
||||||
|
suite.Require().Equal(2+beforeAdd, len(blobs))
|
||||||
|
|
||||||
|
blobs, err = suite.dao.GetBlobsNotRefedByProjectBlob(ctx, 2)
|
||||||
|
suite.Require().Nil(err)
|
||||||
|
suite.Require().Equal(0, len(blobs))
|
||||||
|
}
|
||||||
|
|
||||||
func TestDaoTestSuite(t *testing.T) {
|
func TestDaoTestSuite(t *testing.T) {
|
||||||
suite.Run(t, &DaoTestSuite{})
|
suite.Run(t, &DaoTestSuite{})
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,9 @@ type Manager interface {
|
|||||||
|
|
||||||
// DeleteBlob delete blob
|
// DeleteBlob delete blob
|
||||||
Delete(ctx context.Context, id int64) (err error)
|
Delete(ctx context.Context, id int64) (err error)
|
||||||
|
|
||||||
|
// UselessBlobs useless blob is the blob that is not used in any of projects.
|
||||||
|
UselessBlobs(ctx context.Context, timeWindowHours int64) ([]*models.Blob, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type manager struct {
|
type manager struct {
|
||||||
@ -129,6 +132,10 @@ func (m *manager) Delete(ctx context.Context, id int64) error {
|
|||||||
return m.dao.DeleteBlob(ctx, id)
|
return m.dao.DeleteBlob(ctx, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *manager) UselessBlobs(ctx context.Context, timeWindowHours int64) ([]*models.Blob, error) {
|
||||||
|
return m.dao.GetBlobsNotRefedByProjectBlob(ctx, timeWindowHours)
|
||||||
|
}
|
||||||
|
|
||||||
// NewManager returns blob manager
|
// NewManager returns blob manager
|
||||||
func NewManager() Manager {
|
func NewManager() Manager {
|
||||||
return &manager{dao: dao.New()}
|
return &manager{dao: dao.New()}
|
||||||
|
@ -290,6 +290,32 @@ func (suite *ManagerTestSuite) TestUpdateStatus() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *ManagerTestSuite) TestUselessBlobs() {
|
||||||
|
ctx := suite.Context()
|
||||||
|
|
||||||
|
blobs, err := Mgr.UselessBlobs(ctx, 0)
|
||||||
|
suite.Require().Nil(err)
|
||||||
|
beforeAdd := len(blobs)
|
||||||
|
|
||||||
|
Mgr.Create(ctx, suite.DigestString(), "media type", 100)
|
||||||
|
Mgr.Create(ctx, suite.DigestString(), "media type", 100)
|
||||||
|
digest := suite.DigestString()
|
||||||
|
blobID, err := Mgr.Create(ctx, digest, "media type", 100)
|
||||||
|
suite.Nil(err)
|
||||||
|
|
||||||
|
projectID := int64(1)
|
||||||
|
_, err = Mgr.AssociateWithProject(ctx, blobID, projectID)
|
||||||
|
suite.Nil(err)
|
||||||
|
|
||||||
|
blobs, err = Mgr.UselessBlobs(ctx, 0)
|
||||||
|
suite.Require().Nil(err)
|
||||||
|
suite.Require().Equal(2+beforeAdd, len(blobs))
|
||||||
|
|
||||||
|
blobs, err = Mgr.UselessBlobs(ctx, 2)
|
||||||
|
suite.Require().Nil(err)
|
||||||
|
suite.Require().Equal(0, len(blobs))
|
||||||
|
}
|
||||||
|
|
||||||
func TestManagerTestSuite(t *testing.T) {
|
func TestManagerTestSuite(t *testing.T) {
|
||||||
suite.Run(t, &ManagerTestSuite{})
|
suite.Run(t, &ManagerTestSuite{})
|
||||||
}
|
}
|
||||||
|
@ -220,3 +220,26 @@ func (_m *Manager) UpdateBlobStatus(ctx context.Context, _a1 *models.Blob) (int6
|
|||||||
|
|
||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UselessBlobs provides a mock function with given fields: ctx, timeWindow
|
||||||
|
func (_m *Manager) UselessBlobs(ctx context.Context, timeWindow int64) ([]*models.Blob, error) {
|
||||||
|
ret := _m.Called(ctx, timeWindow)
|
||||||
|
|
||||||
|
var r0 []*models.Blob
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, int64) []*models.Blob); ok {
|
||||||
|
r0 = rf(ctx, timeWindow)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]*models.Blob)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
|
||||||
|
r1 = rf(ctx, timeWindow)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user