0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2024-12-23 22:27:35 -05:00
zot/pkg/meta/repodb/common/common.go
LaurentiuNiculae 5d1f91a79f
feat(repodb): update referrers api to use repodb (#1230)
Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com>
2023-03-10 10:37:29 -08:00

235 lines
5.1 KiB
Go

package common
import (
"encoding/json"
"strings"
"time"
godigest "github.com/opencontainers/go-digest"
ispec "github.com/opencontainers/image-spec/specs-go/v1"
zerr "zotregistry.io/zot/errors"
"zotregistry.io/zot/pkg/meta/repodb"
)
func UpdateManifestMeta(repoMeta repodb.RepoMetadata, manifestDigest godigest.Digest,
manifestMeta repodb.ManifestMetadata,
) repodb.RepoMetadata {
updatedRepoMeta := repoMeta
updatedStatistics := repoMeta.Statistics[manifestDigest.String()]
updatedStatistics.DownloadCount = manifestMeta.DownloadCount
updatedRepoMeta.Statistics[manifestDigest.String()] = updatedStatistics
if manifestMeta.Signatures == nil {
manifestMeta.Signatures = repodb.ManifestSignatures{}
}
updatedRepoMeta.Signatures[manifestDigest.String()] = manifestMeta.Signatures
return updatedRepoMeta
}
func SignatureAlreadyExists(signatureSlice []repodb.SignatureInfo, sm repodb.SignatureMetadata) bool {
for _, sigInfo := range signatureSlice {
if sm.SignatureDigest == sigInfo.SignatureManifestDigest {
return true
}
}
return false
}
func ReferenceIsDigest(reference string) bool {
_, err := godigest.Parse(reference)
return err == nil
}
func ValidateRepoReferenceInput(repo, reference string, manifestDigest godigest.Digest) error {
if repo == "" {
return zerr.ErrEmptyRepoName
}
if reference == "" {
return zerr.ErrEmptyTag
}
if manifestDigest == "" {
return zerr.ErrEmptyDigest
}
return nil
}
func ScoreRepoName(searchText string, repoName string) int {
searchTextSlice := strings.Split(searchText, "/")
repoNameSlice := strings.Split(repoName, "/")
if len(searchTextSlice) > len(repoNameSlice) {
return -1
}
if len(searchTextSlice) == 1 {
// check if it maches first or last name in path
if index := strings.Index(repoNameSlice[len(repoNameSlice)-1], searchTextSlice[0]); index != -1 {
return index + 1
}
// we'll make repos that match the first name in path less important than matching the last name in path
if index := strings.Index(repoNameSlice[0], searchTextSlice[0]); index != -1 {
return (index + 1) * 10
}
return -1
}
if len(searchTextSlice) < len(repoNameSlice) &&
strings.HasPrefix(repoName, searchText) {
return 1
}
// searchText and repoName match perfectly up until the last name in path
for i := 0; i < len(searchTextSlice)-1; i++ {
if searchTextSlice[i] != repoNameSlice[i] {
return -1
}
}
// check the last
if index := strings.Index(repoNameSlice[len(repoNameSlice)-1], searchTextSlice[len(searchTextSlice)-1]); index != -1 {
return (index + 1)
}
return -1
}
func GetImageLastUpdatedTimestamp(configContent ispec.Image) time.Time {
var timeStamp *time.Time
if configContent.Created != nil && !configContent.Created.IsZero() {
return *configContent.Created
}
if len(configContent.History) != 0 {
timeStamp = configContent.History[len(configContent.History)-1].Created
}
if timeStamp == nil {
timeStamp = &time.Time{}
}
return *timeStamp
}
func CheckIsSigned(signatures repodb.ManifestSignatures) bool {
for _, signatures := range signatures {
if len(signatures) > 0 {
return true
}
}
return false
}
func GetRepoTag(searchText string) (string, string, error) {
const repoTagCount = 2
splitSlice := strings.Split(searchText, ":")
if len(splitSlice) != repoTagCount {
return "", "", zerr.ErrInvalidRepoTagFormat
}
repo := strings.TrimSpace(splitSlice[0])
tag := strings.TrimSpace(splitSlice[1])
return repo, tag, nil
}
func GetMapKeys[K comparable, V any](genericMap map[K]V) []K {
keys := make([]K, 0, len(genericMap))
for k := range genericMap {
keys = append(keys, k)
}
return keys
}
// acceptedByFilter checks that data contains at least 1 element of each filter
// criteria(os, arch) present in filter.
func AcceptedByFilter(filter repodb.Filter, data repodb.FilterData) bool {
if filter.Arch != nil {
foundArch := false
for _, arch := range filter.Arch {
foundArch = foundArch || containsString(data.ArchList, *arch)
}
if !foundArch {
return false
}
}
if filter.Os != nil {
foundOs := false
for _, os := range filter.Os {
foundOs = foundOs || containsString(data.OsList, *os)
}
if !foundOs {
return false
}
}
if filter.HasToBeSigned != nil && *filter.HasToBeSigned != data.IsSigned {
return false
}
return true
}
func containsString(strSlice []string, str string) bool {
for _, val := range strSlice {
if strings.EqualFold(val, str) {
return true
}
}
return false
}
func GetReferredSubject(descriptorBlob []byte) (godigest.Digest, bool) {
var manifest ispec.Manifest
err := json.Unmarshal(descriptorBlob, &manifest)
if err != nil {
return "", false
}
if manifest.Subject == nil || manifest.Subject.Digest.String() == "" {
return "", false
}
return manifest.Subject.Digest, true
}
func MatchesArtifactTypes(descriptorMediaType string, artifactTypes []string) bool {
if len(artifactTypes) == 0 {
return true
}
found := false
for _, artifactType := range artifactTypes {
if artifactType != "" && descriptorMediaType != artifactType {
continue
}
found = true
break
}
return found
}