mirror of
https://github.com/project-zot/zot.git
synced 2026-06-18 13:37:57 +08:00
fix: image retention policy to handle patterns even if metadb is not instantiated (#3200)
It is to fix #3185. This fixes the case where MetaDB is not instantiated (none of the conditions match), and we want to retain tags only by pattern (which should not need to use MetaBD). Without this fix you could only use retention to delete untagged manifests. If you specified only the key "patterns" under "keepTags", zot would crash. It was possible to not specify "keepTags" all, which would retain all tags, but it was not possible to retains specific tags. Basically the case quoted below, from the documentation, was broken:: https://zotregistry.dev/v2.1.4/articles/retention/#configuration-example ``` When you specify a regex pattern with no rules other than the default, all tags matching the pattern are retained. ``` This would only work if MetaDb was instantiated by an unrelated configured feature. Signed-off-by: Andrei Aaron <aaaron@luxoft.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package retention
|
||||
|
||||
import (
|
||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
|
||||
mTypes "zotregistry.dev/zot/pkg/meta/types"
|
||||
"zotregistry.dev/zot/pkg/retention/types"
|
||||
)
|
||||
@@ -27,3 +29,25 @@ func GetCandidates(repoMeta mTypes.RepoMeta) []*types.Candidate {
|
||||
|
||||
return candidates
|
||||
}
|
||||
|
||||
func GetCandidatesFromIndex(index ispec.Index) []*types.Candidate {
|
||||
candidates := make([]*types.Candidate, 0)
|
||||
|
||||
// collect all manifests in the repo
|
||||
for _, manifest := range index.Manifests {
|
||||
tag, ok := manifest.Annotations[ispec.AnnotationRefName]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
candidate := &types.Candidate{
|
||||
MediaType: manifest.MediaType,
|
||||
DigestStr: string(manifest.Digest),
|
||||
Tag: tag,
|
||||
}
|
||||
|
||||
candidates = append(candidates, candidate)
|
||||
}
|
||||
|
||||
return candidates
|
||||
}
|
||||
|
||||
@@ -98,7 +98,51 @@ func (p policyManager) getRules(tagPolicy config.KeepTagsPolicy) []types.Rule {
|
||||
return rules
|
||||
}
|
||||
|
||||
func (p policyManager) GetRetainedTags(ctx context.Context, repoMeta mTypes.RepoMeta, index ispec.Index) []string {
|
||||
// GetRetainedTagsFromIndex uses only index information to match tags against patterns and determine
|
||||
// a list of tags to be retained. This function is to be used only in case MetaDB information is not available,
|
||||
// if the DB is not instantiated.
|
||||
func (p policyManager) GetRetainedTagsFromIndex(ctx context.Context, repo string, index ispec.Index) []string {
|
||||
candidates := GetCandidatesFromIndex(index)
|
||||
retainTags := make([]string, 0)
|
||||
|
||||
// group all tags by tag policy
|
||||
grouped := p.groupCandidatesByTagPolicy(repo, candidates)
|
||||
|
||||
for _, candidates := range grouped {
|
||||
if zcommon.IsContextDone(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, retainCandidate := range candidates.candidates {
|
||||
// there may be duplicates
|
||||
if !zcommon.Contains(retainTags, retainCandidate.Tag) {
|
||||
reason := fmt.Sprintf(retainedStrFormat, retainCandidate.RetainedBy)
|
||||
|
||||
logAction(repo, "keep", reason, retainCandidate, p.config.DryRun, &p.log)
|
||||
|
||||
retainTags = append(retainTags, retainCandidate.Tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// log tags which will be removed
|
||||
for _, candidate := range candidates {
|
||||
if !zcommon.Contains(retainTags, candidate.Tag) {
|
||||
logAction(repo, "delete", filteredByTagNames, candidate, p.config.DryRun, &p.log)
|
||||
|
||||
if p.auditLog != nil {
|
||||
logAction(repo, "delete", filteredByTagNames, candidate, p.config.DryRun, p.auditLog)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retainTags
|
||||
}
|
||||
|
||||
// GetRetainedTagsFromMetaDB uses MetaDB information to apply retention rules and obtain a list of tags to be retained.
|
||||
func (p policyManager) GetRetainedTagsFromMetaDB(ctx context.Context, repoMeta mTypes.RepoMeta,
|
||||
index ispec.Index,
|
||||
) []string {
|
||||
repo := repoMeta.Name
|
||||
|
||||
matchedByName := make([]string, 0)
|
||||
|
||||
@@ -22,7 +22,8 @@ type PolicyManager interface {
|
||||
HasDeleteReferrer(repo string) bool
|
||||
HasDeleteUntagged(repo string) bool
|
||||
HasTagRetention(repo string) bool
|
||||
GetRetainedTags(ctx context.Context, repoMeta mTypes.RepoMeta, index ispec.Index) []string
|
||||
GetRetainedTagsFromIndex(ctx context.Context, repo string, index ispec.Index) []string
|
||||
GetRetainedTagsFromMetaDB(ctx context.Context, repoMeta mTypes.RepoMeta, index ispec.Index) []string
|
||||
}
|
||||
|
||||
type Rule interface {
|
||||
|
||||
Reference in New Issue
Block a user