mirror of
https://github.com/project-zot/zot.git
synced 2024-12-16 21:56:37 -05:00
ce4924f841
Signed-off-by: Andrei Aaron <aaaron@luxoft.com>
140 lines
3 KiB
Go
140 lines
3 KiB
Go
package retention
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"time"
|
|
|
|
"zotregistry.dev/zot/pkg/retention/types"
|
|
)
|
|
|
|
const (
|
|
// rules name.
|
|
daysPullName = "pulledWithin"
|
|
daysPushName = "pushedWithin"
|
|
latestPullName = "mostRecentlyPulledCount"
|
|
latestPushName = "mostRecentlyPushedCount"
|
|
)
|
|
|
|
// rules implementatio
|
|
|
|
type DaysPull struct {
|
|
duration time.Duration
|
|
}
|
|
|
|
func NewDaysPull(duration time.Duration) DaysPull {
|
|
return DaysPull{duration: duration}
|
|
}
|
|
|
|
func (dp DaysPull) Name() string {
|
|
return fmt.Sprintf("%s:%d", daysPullName, dp.duration)
|
|
}
|
|
|
|
func (dp DaysPull) Perform(candidates []*types.Candidate) []*types.Candidate {
|
|
filtered := make([]*types.Candidate, 0)
|
|
|
|
timestamp := time.Now().Add(-dp.duration)
|
|
|
|
for _, candidate := range candidates {
|
|
// we check pushtimestamp because we don't want to delete tags pushed after timestamp
|
|
// ie: if the tag doesn't meet PulledWithin: "3days" and the image is 1day old then do not remove!
|
|
if candidate.PullTimestamp.After(timestamp) || candidate.PushTimestamp.After(timestamp) {
|
|
candidate.RetainedBy = dp.Name()
|
|
filtered = append(filtered, candidate)
|
|
}
|
|
}
|
|
|
|
return filtered
|
|
}
|
|
|
|
type DaysPush struct {
|
|
duration time.Duration
|
|
}
|
|
|
|
func NewDaysPush(duration time.Duration) DaysPush {
|
|
return DaysPush{duration: duration}
|
|
}
|
|
|
|
func (dp DaysPush) Name() string {
|
|
return fmt.Sprintf("%s:%d", daysPushName, dp.duration)
|
|
}
|
|
|
|
func (dp DaysPush) Perform(candidates []*types.Candidate) []*types.Candidate {
|
|
filtered := make([]*types.Candidate, 0)
|
|
|
|
timestamp := time.Now().Add(-dp.duration)
|
|
|
|
for _, candidate := range candidates {
|
|
if candidate.PushTimestamp.After(timestamp) {
|
|
candidate.RetainedBy = dp.Name()
|
|
|
|
filtered = append(filtered, candidate)
|
|
}
|
|
}
|
|
|
|
return filtered
|
|
}
|
|
|
|
type latestPull struct {
|
|
count int
|
|
}
|
|
|
|
func NewLatestPull(count int) latestPull {
|
|
return latestPull{count: count}
|
|
}
|
|
|
|
func (lp latestPull) Name() string {
|
|
return fmt.Sprintf("%s:%d", latestPullName, lp.count)
|
|
}
|
|
|
|
func (lp latestPull) Perform(candidates []*types.Candidate) []*types.Candidate {
|
|
sort.Slice(candidates, func(i, j int) bool {
|
|
return candidates[i].PullTimestamp.After(candidates[j].PullTimestamp)
|
|
})
|
|
|
|
// take top count candidates
|
|
upper := lp.count
|
|
if lp.count > len(candidates) {
|
|
upper = len(candidates)
|
|
}
|
|
|
|
candidates = candidates[:upper]
|
|
|
|
for _, candidate := range candidates {
|
|
candidate.RetainedBy = lp.Name()
|
|
}
|
|
|
|
return candidates
|
|
}
|
|
|
|
type latestPush struct {
|
|
count int
|
|
}
|
|
|
|
func NewLatestPush(count int) latestPush {
|
|
return latestPush{count: count}
|
|
}
|
|
|
|
func (lp latestPush) Name() string {
|
|
return fmt.Sprintf("%s:%d", latestPushName, lp.count)
|
|
}
|
|
|
|
func (lp latestPush) Perform(candidates []*types.Candidate) []*types.Candidate {
|
|
sort.Slice(candidates, func(i, j int) bool {
|
|
return candidates[i].PushTimestamp.After(candidates[j].PushTimestamp)
|
|
})
|
|
|
|
// take top count candidates
|
|
upper := lp.count
|
|
if lp.count > len(candidates) {
|
|
upper = len(candidates)
|
|
}
|
|
|
|
candidates = candidates[:upper]
|
|
|
|
for _, candidate := range candidates {
|
|
candidate.RetainedBy = lp.Name()
|
|
}
|
|
|
|
return candidates
|
|
}
|