mirror of
https://github.com/project-zot/zot.git
synced 2025-01-13 22:50:38 -05:00
fix(convert): now returned annotations for an index will fallback to annotations from a random manifest if the annotations field is not present on the index manifest (#1667)
Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com>
This commit is contained in:
parent
cad564b9ee
commit
fce9a02ed5
4 changed files with 293 additions and 3 deletions
|
@ -154,7 +154,7 @@ func searchCve(searchConfig searchConfig) error {
|
|||
}
|
||||
|
||||
for _, searcher := range searchers {
|
||||
// there can be CVE DB readyness issues on the server side
|
||||
// there can be CVE DB readiness issues on the server side
|
||||
// we need a retry mechanism for that specific type of errors
|
||||
maxAttempts := 20
|
||||
|
||||
|
|
|
@ -133,3 +133,58 @@ func GetAnnotations(annotations, labels map[string]string) ImageAnnotations {
|
|||
Authors: authors,
|
||||
}
|
||||
}
|
||||
|
||||
func GetIndexAnnotations(indexAnnotations, manifestAnnotations, manifestLabels map[string]string) ImageAnnotations {
|
||||
annotationsFromManifest := GetAnnotations(manifestAnnotations, manifestLabels)
|
||||
|
||||
description := GetDescription(indexAnnotations)
|
||||
if description == "" {
|
||||
description = annotationsFromManifest.Description
|
||||
}
|
||||
|
||||
title := GetTitle(indexAnnotations)
|
||||
if title == "" {
|
||||
title = annotationsFromManifest.Title
|
||||
}
|
||||
|
||||
documentation := GetDocumentation(indexAnnotations)
|
||||
if documentation == "" {
|
||||
documentation = annotationsFromManifest.Documentation
|
||||
}
|
||||
|
||||
source := GetSource(indexAnnotations)
|
||||
if source == "" {
|
||||
source = annotationsFromManifest.Source
|
||||
}
|
||||
|
||||
licenses := GetLicenses(indexAnnotations)
|
||||
if licenses == "" {
|
||||
licenses = annotationsFromManifest.Licenses
|
||||
}
|
||||
|
||||
categories := GetCategories(indexAnnotations)
|
||||
if categories == "" {
|
||||
categories = annotationsFromManifest.Labels
|
||||
}
|
||||
|
||||
vendor := GetVendor(indexAnnotations)
|
||||
if vendor == "" {
|
||||
vendor = annotationsFromManifest.Vendor
|
||||
}
|
||||
|
||||
authors := GetAuthors(indexAnnotations)
|
||||
if authors == "" {
|
||||
authors = annotationsFromManifest.Authors
|
||||
}
|
||||
|
||||
return ImageAnnotations{
|
||||
Description: description,
|
||||
Title: title,
|
||||
Documentation: documentation,
|
||||
Source: source,
|
||||
Licenses: licenses,
|
||||
Labels: categories,
|
||||
Vendor: vendor,
|
||||
Authors: authors,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -770,3 +770,213 @@ func TestPaginatedConvert(t *testing.T) {
|
|||
So(pageInfo.ItemCount, ShouldEqual, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetOneManifestAnnotations(t *testing.T) {
|
||||
Convey("GetOneManifestAnnotations errors", t, func() {
|
||||
manifestAnnotations, configLabels := convert.GetOneManifestAnnotations(
|
||||
ispec.Index{Manifests: []ispec.Descriptor{
|
||||
{Digest: "bad-manifest"}, {Digest: "dig2"},
|
||||
}},
|
||||
map[string]mTypes.ManifestMetadata{
|
||||
"bad-manifest": {
|
||||
ManifestBlob: []byte(`bad`),
|
||||
ConfigBlob: []byte("{}"),
|
||||
},
|
||||
},
|
||||
)
|
||||
So(manifestAnnotations, ShouldBeEmpty)
|
||||
So(configLabels, ShouldBeEmpty)
|
||||
|
||||
manifestAnnotations, configLabels = convert.GetOneManifestAnnotations(
|
||||
ispec.Index{Manifests: []ispec.Descriptor{
|
||||
{Digest: "bad-config"},
|
||||
}},
|
||||
map[string]mTypes.ManifestMetadata{
|
||||
"bad-config": {
|
||||
ManifestBlob: []byte("{}"),
|
||||
ConfigBlob: []byte("bad"),
|
||||
},
|
||||
},
|
||||
)
|
||||
So(manifestAnnotations, ShouldBeEmpty)
|
||||
So(configLabels, ShouldBeEmpty)
|
||||
})
|
||||
|
||||
Convey("Test ImageIndex2ImageSummary annotations logic", t, func() {
|
||||
ctx := context.Background()
|
||||
|
||||
configLabels := map[string]string{
|
||||
ispec.AnnotationDescription: "ConfigDescription",
|
||||
ispec.AnnotationLicenses: "ConfigLicenses",
|
||||
ispec.AnnotationVendor: "ConfigVendor",
|
||||
ispec.AnnotationAuthors: "ConfigAuthors",
|
||||
ispec.AnnotationTitle: "ConfigTitle",
|
||||
ispec.AnnotationDocumentation: "ConfigDocumentation",
|
||||
ispec.AnnotationSource: "ConfigSource",
|
||||
}
|
||||
|
||||
manifestAnnotations := map[string]string{
|
||||
ispec.AnnotationDescription: "ManifestDescription",
|
||||
ispec.AnnotationLicenses: "ManifestLicenses",
|
||||
ispec.AnnotationVendor: "ManifestVendor",
|
||||
ispec.AnnotationAuthors: "ManifestAuthors",
|
||||
ispec.AnnotationTitle: "ManifestTitle",
|
||||
ispec.AnnotationDocumentation: "ManifestDocumentation",
|
||||
ispec.AnnotationSource: "ManifestSource",
|
||||
}
|
||||
|
||||
indexAnnotations := map[string]string{
|
||||
ispec.AnnotationDescription: "IndexDescription",
|
||||
ispec.AnnotationLicenses: "IndexLicenses",
|
||||
ispec.AnnotationVendor: "IndexVendor",
|
||||
ispec.AnnotationAuthors: "IndexAuthors",
|
||||
ispec.AnnotationTitle: "IndexTitle",
|
||||
ispec.AnnotationDocumentation: "IndexDocumentation",
|
||||
ispec.AnnotationSource: "IndexSource",
|
||||
}
|
||||
|
||||
imageWithConfigAnnotations := test.CreateImageWith().DefaultLayers().
|
||||
ImageConfig(ispec.Image{
|
||||
Config: ispec.ImageConfig{
|
||||
Labels: configLabels,
|
||||
},
|
||||
}).Build()
|
||||
|
||||
imageWithManifestAndConfigAnnotations := test.CreateImageWith().DefaultLayers().
|
||||
ImageConfig(ispec.Image{
|
||||
Config: ispec.ImageConfig{
|
||||
Labels: configLabels,
|
||||
},
|
||||
}).Annotations(manifestAnnotations).Build()
|
||||
|
||||
// --------------------------------------------------------
|
||||
indexWithAnnotations := test.CreateMultiarchWith().Images(
|
||||
[]test.Image{imageWithManifestAndConfigAnnotations},
|
||||
).Annotations(indexAnnotations).Build()
|
||||
|
||||
repoMeta, manifestMetadata, indexData := test.GetMetadataForRepos(test.Repo{
|
||||
Name: "repo",
|
||||
MultiArchImages: []test.RepoMultiArchImage{
|
||||
{MultiarchImage: indexWithAnnotations, Tag: "tag"},
|
||||
},
|
||||
})
|
||||
|
||||
digest := indexWithAnnotations.Digest()
|
||||
|
||||
imageSummary, _, err := convert.ImageIndex2ImageSummary(ctx, "repo", "tag", digest, true, repoMeta[0],
|
||||
indexData[digest.String()], manifestMetadata, nil)
|
||||
So(err, ShouldBeNil)
|
||||
So(*imageSummary.Description, ShouldResemble, "IndexDescription")
|
||||
So(*imageSummary.Licenses, ShouldResemble, "IndexLicenses")
|
||||
So(*imageSummary.Title, ShouldResemble, "IndexTitle")
|
||||
So(*imageSummary.Source, ShouldResemble, "IndexSource")
|
||||
So(*imageSummary.Documentation, ShouldResemble, "IndexDocumentation")
|
||||
So(*imageSummary.Vendor, ShouldResemble, "IndexVendor")
|
||||
So(*imageSummary.Authors, ShouldResemble, "IndexAuthors")
|
||||
|
||||
// --------------------------------------------------------
|
||||
indexWithManifestAndConfigAnnotations := test.CreateMultiarchWith().Images(
|
||||
[]test.Image{imageWithManifestAndConfigAnnotations, test.CreateRandomImage(), test.CreateRandomImage()},
|
||||
).Build()
|
||||
|
||||
repoMeta, manifestMetadata, indexData = test.GetMetadataForRepos(test.Repo{
|
||||
Name: "repo",
|
||||
MultiArchImages: []test.RepoMultiArchImage{{MultiarchImage: indexWithManifestAndConfigAnnotations}},
|
||||
})
|
||||
digest = indexWithManifestAndConfigAnnotations.Digest()
|
||||
|
||||
imageSummary, _, err = convert.ImageIndex2ImageSummary(ctx, "repo", "tag", digest,
|
||||
true, repoMeta[0], indexData[digest.String()], manifestMetadata, nil)
|
||||
So(err, ShouldBeNil)
|
||||
So(*imageSummary.Description, ShouldResemble, "ManifestDescription")
|
||||
So(*imageSummary.Licenses, ShouldResemble, "ManifestLicenses")
|
||||
So(*imageSummary.Title, ShouldResemble, "ManifestTitle")
|
||||
So(*imageSummary.Source, ShouldResemble, "ManifestSource")
|
||||
So(*imageSummary.Documentation, ShouldResemble, "ManifestDocumentation")
|
||||
So(*imageSummary.Vendor, ShouldResemble, "ManifestVendor")
|
||||
So(*imageSummary.Authors, ShouldResemble, "ManifestAuthors")
|
||||
// --------------------------------------------------------
|
||||
indexWithConfigAnnotations := test.CreateMultiarchWith().Images(
|
||||
[]test.Image{imageWithConfigAnnotations, test.CreateRandomImage(), test.CreateRandomImage()},
|
||||
).Build()
|
||||
|
||||
repoMeta, manifestMetadata, indexData = test.GetMetadataForRepos(test.Repo{
|
||||
Name: "repo",
|
||||
MultiArchImages: []test.RepoMultiArchImage{{MultiarchImage: indexWithConfigAnnotations, Tag: "tag"}},
|
||||
})
|
||||
digest = indexWithConfigAnnotations.Digest()
|
||||
|
||||
imageSummary, _, err = convert.ImageIndex2ImageSummary(ctx, "repo", "tag", digest,
|
||||
true, repoMeta[0], indexData[digest.String()], manifestMetadata, nil)
|
||||
So(err, ShouldBeNil)
|
||||
So(*imageSummary.Description, ShouldResemble, "ConfigDescription")
|
||||
So(*imageSummary.Licenses, ShouldResemble, "ConfigLicenses")
|
||||
So(*imageSummary.Title, ShouldResemble, "ConfigTitle")
|
||||
So(*imageSummary.Source, ShouldResemble, "ConfigSource")
|
||||
So(*imageSummary.Documentation, ShouldResemble, "ConfigDocumentation")
|
||||
So(*imageSummary.Vendor, ShouldResemble, "ConfigVendor")
|
||||
So(*imageSummary.Authors, ShouldResemble, "ConfigAuthors")
|
||||
//--------------------------------------------------------
|
||||
|
||||
indexWithMixAnnotations := test.CreateMultiarchWith().Images(
|
||||
[]test.Image{
|
||||
test.CreateImageWith().DefaultLayers().ImageConfig(ispec.Image{
|
||||
Config: ispec.ImageConfig{
|
||||
Labels: map[string]string{
|
||||
ispec.AnnotationDescription: "ConfigDescription",
|
||||
ispec.AnnotationLicenses: "ConfigLicenses",
|
||||
},
|
||||
},
|
||||
}).Annotations(map[string]string{
|
||||
ispec.AnnotationVendor: "ManifestVendor",
|
||||
ispec.AnnotationAuthors: "ManifestAuthors",
|
||||
}).Build(),
|
||||
test.CreateRandomImage(),
|
||||
test.CreateRandomImage(),
|
||||
},
|
||||
).Annotations(
|
||||
map[string]string{
|
||||
ispec.AnnotationTitle: "IndexTitle",
|
||||
ispec.AnnotationDocumentation: "IndexDocumentation",
|
||||
ispec.AnnotationSource: "IndexSource",
|
||||
},
|
||||
).Build()
|
||||
|
||||
repoMeta, manifestMetadata, indexData = test.GetMetadataForRepos(test.Repo{
|
||||
Name: "repo",
|
||||
MultiArchImages: []test.RepoMultiArchImage{{MultiarchImage: indexWithMixAnnotations, Tag: "tag"}},
|
||||
})
|
||||
digest = indexWithMixAnnotations.Digest()
|
||||
|
||||
imageSummary, _, err = convert.ImageIndex2ImageSummary(ctx, "repo", "tag", digest,
|
||||
true, repoMeta[0], indexData[digest.String()], manifestMetadata, nil)
|
||||
So(err, ShouldBeNil)
|
||||
So(*imageSummary.Description, ShouldResemble, "ConfigDescription")
|
||||
So(*imageSummary.Licenses, ShouldResemble, "ConfigLicenses")
|
||||
So(*imageSummary.Vendor, ShouldResemble, "ManifestVendor")
|
||||
So(*imageSummary.Authors, ShouldResemble, "ManifestAuthors")
|
||||
So(*imageSummary.Title, ShouldResemble, "IndexTitle")
|
||||
So(*imageSummary.Documentation, ShouldResemble, "IndexDocumentation")
|
||||
So(*imageSummary.Source, ShouldResemble, "IndexSource")
|
||||
|
||||
//--------------------------------------------------------
|
||||
indexWithNoAnnotations := test.CreateRandomMultiarch()
|
||||
|
||||
repoMeta, manifestMetadata, indexData = test.GetMetadataForRepos(test.Repo{
|
||||
Name: "repo",
|
||||
MultiArchImages: []test.RepoMultiArchImage{{MultiarchImage: indexWithNoAnnotations, Tag: "tag"}},
|
||||
})
|
||||
digest = indexWithNoAnnotations.Digest()
|
||||
|
||||
imageSummary, _, err = convert.ImageIndex2ImageSummary(ctx, "repo", "tag", digest,
|
||||
true, repoMeta[0], indexData[digest.String()], manifestMetadata, nil)
|
||||
So(err, ShouldBeNil)
|
||||
So(*imageSummary.Description, ShouldBeBlank)
|
||||
So(*imageSummary.Licenses, ShouldBeBlank)
|
||||
So(*imageSummary.Vendor, ShouldBeBlank)
|
||||
So(*imageSummary.Authors, ShouldBeBlank)
|
||||
So(*imageSummary.Title, ShouldBeBlank)
|
||||
So(*imageSummary.Documentation, ShouldBeBlank)
|
||||
So(*imageSummary.Source, ShouldBeBlank)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -268,10 +268,11 @@ func ImageIndex2ImageSummary(ctx context.Context, repo, tag string, indexDigest
|
|||
|
||||
indexSize = strconv.FormatInt(totalIndexSize, 10)
|
||||
|
||||
annotations := GetAnnotations(indexContent.Annotations, map[string]string{})
|
||||
|
||||
signaturesInfo := GetSignaturesInfo(isSigned, repoMeta, indexDigest)
|
||||
|
||||
manifestAnnotations, configLabels := GetOneManifestAnnotations(indexContent, manifestMetaMap)
|
||||
annotations := GetIndexAnnotations(indexContent.Annotations, manifestAnnotations, configLabels)
|
||||
|
||||
indexSummary := gql_generated.ImageSummary{
|
||||
RepoName: &repo,
|
||||
Tag: &tag,
|
||||
|
@ -301,6 +302,30 @@ func ImageIndex2ImageSummary(ctx context.Context, repo, tag string, indexDigest
|
|||
return &indexSummary, indexBlobs, nil
|
||||
}
|
||||
|
||||
func GetOneManifestAnnotations(indexContent ispec.Index, manifestMetaMap map[string]mTypes.ManifestMetadata,
|
||||
) (map[string]string, map[string]string) {
|
||||
if len(manifestMetaMap) == 0 || len(indexContent.Manifests) == 0 {
|
||||
return map[string]string{}, map[string]string{}
|
||||
}
|
||||
|
||||
manifestMeta := manifestMetaMap[indexContent.Manifests[0].Digest.String()]
|
||||
|
||||
manifestContent := ispec.Manifest{}
|
||||
configContent := ispec.Image{}
|
||||
|
||||
err := json.Unmarshal(manifestMeta.ManifestBlob, &manifestContent)
|
||||
if err != nil {
|
||||
return map[string]string{}, map[string]string{}
|
||||
}
|
||||
|
||||
err = json.Unmarshal(manifestMeta.ConfigBlob, &configContent)
|
||||
if err != nil {
|
||||
return map[string]string{}, map[string]string{}
|
||||
}
|
||||
|
||||
return manifestContent.Annotations, configContent.Config.Labels
|
||||
}
|
||||
|
||||
func ImageManifest2ImageSummary(ctx context.Context, repo, tag string, digest godigest.Digest, skipCVE bool,
|
||||
repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata, cveInfo cveinfo.CveInfo,
|
||||
) (*gql_generated.ImageSummary, map[string]int64, error) {
|
||||
|
|
Loading…
Add table
Reference in a new issue