feat(search): add referrers field to ImageSummary (#1261)

Changed repodb to store more information about the referrer needed for the referrers query

Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com>
This commit is contained in:
LaurentiuNiculae
2023-03-20 18:14:17 +02:00
committed by GitHub
parent 17a554b504
commit ed01292ad2
20 changed files with 472 additions and 394 deletions
+54 -28
View File
@@ -1024,10 +1024,7 @@ func TestGetReferrersGQL(t *testing.T) {
gqlQuery := `
{
Referrers(
repo: "%s",
digest: "%s",
type: ""
){
repo: "%s", digest: "%s", type: ""){
ArtifactType,
Digest,
MediaType,
@@ -1756,6 +1753,13 @@ func TestUtilsMethod(t *testing.T) {
fixedTags := common.GetFixedTags(allTags, vulnerableTags)
So(len(fixedTags), ShouldEqual, 2)
fixedTags = common.GetFixedTags(allTags, append(vulnerableTags, common.TagInfo{
Name: "taginfo",
Descriptor: common.Descriptor{},
Timestamp: time.Date(2000, time.July, 20, 10, 10, 10, 10, time.UTC),
}))
So(len(fixedTags), ShouldEqual, 3)
log := log.NewLogger("debug", "")
rootDir := t.TempDir()
@@ -6395,6 +6399,7 @@ func TestImageSummary(t *testing.T) {
conf := config.New()
conf.HTTP.Port = port
conf.Storage.RootDirectory = t.TempDir()
conf.Storage.GC = false
defaultVal := true
conf.Extensions = &extconf.ExtensionConfig{
@@ -6426,6 +6431,7 @@ func TestImageSummary(t *testing.T) {
LastUpdated
Size
Vulnerabilities { Count MaxSeverity }
Referrers {MediaType ArtifactType Digest Annotations {Key Value}}
}
}`
@@ -6452,38 +6458,51 @@ func TestImageSummary(t *testing.T) {
}`
gqlEndpoint := fmt.Sprintf("%s%s?query=", baseURL, graphqlQueryPrefix)
config, layers, manifest, err := GetImageComponents(100)
So(err, ShouldBeNil)
createdTime := time.Date(2010, 1, 1, 12, 0, 0, 0, time.UTC)
config.History = append(config.History, ispec.History{Created: &createdTime})
manifest, err = updateManifestConfig(manifest, config)
So(err, ShouldBeNil)
configBlob, errConfig := json.Marshal(config)
configDigest := godigest.FromBytes(configBlob)
So(errConfig, ShouldBeNil) // marshall success, config is valid JSON
ctlrManager := NewControllerManager(ctlr)
ctlrManager.StartAndWait(port)
defer ctlrManager.StopServer()
manifestBlob, errMarsal := json.Marshal(manifest)
So(errMarsal, ShouldBeNil)
So(manifestBlob, ShouldNotBeNil)
manifestDigest := godigest.FromBytes(manifestBlob)
repoName := "test-repo" //nolint:goconst
tagTarget := "latest"
err = UploadImage(
Image{
Manifest: manifest,
Config: config,
Layers: layers,
Reference: tagTarget,
createdTime := time.Date(2010, 1, 1, 12, 0, 0, 0, time.UTC)
image, err := GetImageWithConfig(
ispec.Image{
History: []ispec.History{{Created: &createdTime}},
Platform: ispec.Platform{
Architecture: "amd64",
OS: "linux",
},
},
baseURL,
repoName,
)
So(err, ShouldBeNil)
image.Reference = tagTarget
manifestDigest, err := image.Digest()
So(err, ShouldBeNil)
err = UploadImage(image, baseURL, repoName)
So(err, ShouldBeNil)
// ------ Add a referrer
referrerImage, err := GetImageWithConfig(ispec.Image{})
So(err, ShouldBeNil)
referrerImage.Manifest.Subject = &ispec.Descriptor{
Digest: manifestDigest,
MediaType: ispec.MediaTypeImageManifest,
}
referrerImage.Manifest.Config.MediaType = "test.artifact.type"
referrerImage.Manifest.Annotations = map[string]string{"testAnnotationKey": "testAnnotationValue"}
referrerManifestDigest, err := referrerImage.Digest()
So(err, ShouldBeNil)
referrerImage.Reference = referrerManifestDigest.String()
err = UploadImage(referrerImage, baseURL, repoName)
So(err, ShouldBeNil)
var (
imgSummaryResponse ImageSummaryResult
strQuery string
@@ -6531,11 +6550,11 @@ func TestImageSummary(t *testing.T) {
imgSummary := imgSummaryResponse.SingleImageSummary.ImageSummary
So(imgSummary.RepoName, ShouldContainSubstring, repoName)
So(imgSummary.Tag, ShouldContainSubstring, tagTarget)
So(imgSummary.Manifests[0].ConfigDigest, ShouldContainSubstring, configDigest.Encoded())
So(imgSummary.Manifests[0].ConfigDigest, ShouldContainSubstring, image.Manifest.Config.Digest.Encoded())
So(imgSummary.Manifests[0].Digest, ShouldContainSubstring, manifestDigest.Encoded())
So(len(imgSummary.Manifests[0].Layers), ShouldEqual, 1)
So(imgSummary.Manifests[0].Layers[0].Digest, ShouldContainSubstring,
godigest.FromBytes(layers[0]).Encoded())
image.Manifest.Layers[0].Digest.Encoded())
So(imgSummary.LastUpdated, ShouldEqual, createdTime)
So(imgSummary.IsSigned, ShouldEqual, false)
So(imgSummary.Manifests[0].Platform.Os, ShouldEqual, "linux")
@@ -6545,6 +6564,13 @@ func TestImageSummary(t *testing.T) {
// No vulnerabilities should be detected since trivy is disabled
So(imgSummary.Vulnerabilities.Count, ShouldEqual, 0)
So(imgSummary.Vulnerabilities.MaxSeverity, ShouldEqual, "")
So(len(imgSummary.Referrers), ShouldEqual, 1)
So(imgSummary.Referrers[0], ShouldResemble, common.Referrer{
MediaType: ispec.MediaTypeImageManifest,
ArtifactType: "test.artifact.type",
Digest: referrerManifestDigest.String(),
Annotations: []common.Annotation{{Key: "testAnnotationKey", Value: "testAnnotationValue"}},
})
t.Log("starting Test retrieve duplicated image same layers based on image identifier")
// gqlEndpoint
+1
View File
@@ -37,6 +37,7 @@ type ImageSummary struct {
Authors string `json:"authors"`
Vendor string `json:"vendor"`
Vulnerabilities ImageVulnerabilitySummary `json:"vulnerabilities"`
Referrers []Referrer `json:"referrers"`
}
type ManifestSummary struct {
@@ -172,6 +172,7 @@ func TestConvertErrors(t *testing.T) {
ManifestBlob: []byte("{}"),
ConfigBlob: []byte("bad json"),
},
nil,
mocks.CveInfoMock{
GetCVESummaryForImageFn: func(repo, reference string,
) (cveinfo.ImageCVESummary, error) {
@@ -203,6 +204,7 @@ func TestConvertErrors(t *testing.T) {
ManifestBlob: []byte("{}"),
ConfigBlob: configBlob,
},
nil,
mocks.CveInfoMock{
GetCVESummaryForImageFn: func(repo, reference string,
) (cveinfo.ImageCVESummary, error) {
+39 -2
View File
@@ -193,7 +193,7 @@ func ImageIndex2ImageSummary(ctx context.Context, repo, tag string, indexDigest
for _, descriptor := range indexContent.Manifests {
manifestSummary, manifestBlobs, err := ImageManifest2ManifestSummary(ctx, repo, tag, descriptor, false,
manifestMetaMap[descriptor.Digest.String()], cveInfo)
manifestMetaMap[descriptor.Digest.String()], repoMeta.Referrers[descriptor.Digest.String()], cveInfo)
if err != nil {
return &gql_generated.ImageSummary{}, map[string]int64{}, err
}
@@ -260,6 +260,7 @@ func ImageIndex2ImageSummary(ctx context.Context, repo, tag string, indexDigest
MaxSeverity: &imageCveSummary.MaxSeverity,
Count: &imageCveSummary.Count,
},
Referrers: getReferrers(repoMeta.Referrers[indexDigest.String()]),
}
return &indexSummary, indexBlobs, nil
@@ -382,13 +383,48 @@ func ImageManifest2ImageSummary(ctx context.Context, repo, tag string, digest go
MaxSeverity: &imageCveSummary.MaxSeverity,
Count: &imageCveSummary.Count,
},
Referrers: getReferrers(repoMeta.Referrers[manifestDigest]),
}
return &imageSummary, imageBlobsMap, nil
}
func getReferrers(referrersInfo []repodb.ReferrerInfo) []*gql_generated.Referrer {
referrers := make([]*gql_generated.Referrer, 0, len(referrersInfo))
for _, referrerInfo := range referrersInfo {
referrerInfo := referrerInfo
referrers = append(referrers, &gql_generated.Referrer{
MediaType: &referrerInfo.MediaType,
ArtifactType: &referrerInfo.ArtifactType,
Size: &referrerInfo.Size,
Digest: &referrerInfo.Digest,
Annotations: getAnnotationsFromMap(referrerInfo.Annotations),
})
}
return referrers
}
func getAnnotationsFromMap(annotationsMap map[string]string) []*gql_generated.Annotation {
annotations := make([]*gql_generated.Annotation, 0, len(annotationsMap))
for key, value := range annotationsMap {
key := key
value := value
annotations = append(annotations, &gql_generated.Annotation{
Key: &key,
Value: &value,
})
}
return annotations
}
func ImageManifest2ManifestSummary(ctx context.Context, repo, tag string, descriptor ispec.Descriptor,
skipCVE bool, manifestMeta repodb.ManifestMetadata, cveInfo cveinfo.CveInfo,
skipCVE bool, manifestMeta repodb.ManifestMetadata, referrersInfo []repodb.ReferrerInfo, cveInfo cveinfo.CveInfo,
) (*gql_generated.ManifestSummary, map[string]int64, error) {
var (
manifestContent ispec.Manifest
@@ -469,6 +505,7 @@ func ImageManifest2ManifestSummary(ctx context.Context, repo, tag string, descri
MaxSeverity: &imageCveSummary.MaxSeverity,
Count: &imageCveSummary.Count,
},
Referrers: getReferrers(referrersInfo),
}
return &manifestSummary, imageBlobsMap, nil
@@ -86,6 +86,7 @@ type ComplexityRoot struct {
LastUpdated func(childComplexity int) int
Licenses func(childComplexity int) int
Manifests func(childComplexity int) int
Referrers func(childComplexity int) int
RepoName func(childComplexity int) int
Score func(childComplexity int) int
Size func(childComplexity int) int
@@ -120,6 +121,7 @@ type ComplexityRoot struct {
LastUpdated func(childComplexity int) int
Layers func(childComplexity int) int
Platform func(childComplexity int) int
Referrers func(childComplexity int) int
Size func(childComplexity int) int
Vulnerabilities func(childComplexity int) int
}
@@ -419,6 +421,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.ImageSummary.Manifests(childComplexity), true
case "ImageSummary.Referrers":
if e.complexity.ImageSummary.Referrers == nil {
break
}
return e.complexity.ImageSummary.Referrers(childComplexity), true
case "ImageSummary.RepoName":
if e.complexity.ImageSummary.RepoName == nil {
break
@@ -573,6 +582,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.ManifestSummary.Platform(childComplexity), true
case "ManifestSummary.Referrers":
if e.complexity.ManifestSummary.Referrers == nil {
break
}
return e.complexity.ManifestSummary.Referrers(childComplexity), true
case "ManifestSummary.Size":
if e.complexity.ManifestSummary.Size == nil {
break
@@ -1175,6 +1191,10 @@ type ImageSummary {
Short summary of the identified CVEs
"""
Vulnerabilities: ImageVulnerabilitySummary
"""
Information about objects that reference this image
"""
Referrers: [Referrer]
}
"""
Details about a specific version of an image for a certain operating system and architecture.
@@ -1217,6 +1237,10 @@ type ManifestSummary {
Short summary of the identified CVEs
"""
Vulnerabilities: ImageVulnerabilitySummary
"""
Information about objects that reference this image
"""
Referrers: [Referrer]
}
"""
@@ -2593,6 +2617,8 @@ func (ec *executionContext) fieldContext_GlobalSearchResult_Images(ctx context.C
return ec.fieldContext_ImageSummary_Authors(ctx, field)
case "Vulnerabilities":
return ec.fieldContext_ImageSummary_Vulnerabilities(ctx, field)
case "Referrers":
return ec.fieldContext_ImageSummary_Referrers(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type ImageSummary", field.Name)
},
@@ -3055,6 +3081,8 @@ func (ec *executionContext) fieldContext_ImageSummary_Manifests(ctx context.Cont
return ec.fieldContext_ManifestSummary_History(ctx, field)
case "Vulnerabilities":
return ec.fieldContext_ManifestSummary_Vulnerabilities(ctx, field)
case "Referrers":
return ec.fieldContext_ManifestSummary_Referrers(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type ManifestSummary", field.Name)
},
@@ -3642,6 +3670,59 @@ func (ec *executionContext) fieldContext_ImageSummary_Vulnerabilities(ctx contex
return fc, nil
}
func (ec *executionContext) _ImageSummary_Referrers(ctx context.Context, field graphql.CollectedField, obj *ImageSummary) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_ImageSummary_Referrers(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.Referrers, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.([]*Referrer)
fc.Result = res
return ec.marshalOReferrer2ᚕᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐReferrer(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_ImageSummary_Referrers(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "ImageSummary",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
switch field.Name {
case "MediaType":
return ec.fieldContext_Referrer_MediaType(ctx, field)
case "ArtifactType":
return ec.fieldContext_Referrer_ArtifactType(ctx, field)
case "Size":
return ec.fieldContext_Referrer_Size(ctx, field)
case "Digest":
return ec.fieldContext_Referrer_Digest(ctx, field)
case "Annotations":
return ec.fieldContext_Referrer_Annotations(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type Referrer", field.Name)
},
}
return fc, nil
}
func (ec *executionContext) _ImageVulnerabilitySummary_MaxSeverity(ctx context.Context, field graphql.CollectedField, obj *ImageVulnerabilitySummary) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_ImageVulnerabilitySummary_MaxSeverity(ctx, field)
if err != nil {
@@ -4344,6 +4425,59 @@ func (ec *executionContext) fieldContext_ManifestSummary_Vulnerabilities(ctx con
return fc, nil
}
func (ec *executionContext) _ManifestSummary_Referrers(ctx context.Context, field graphql.CollectedField, obj *ManifestSummary) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_ManifestSummary_Referrers(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.Referrers, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.([]*Referrer)
fc.Result = res
return ec.marshalOReferrer2ᚕᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐReferrer(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_ManifestSummary_Referrers(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "ManifestSummary",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
switch field.Name {
case "MediaType":
return ec.fieldContext_Referrer_MediaType(ctx, field)
case "ArtifactType":
return ec.fieldContext_Referrer_ArtifactType(ctx, field)
case "Size":
return ec.fieldContext_Referrer_Size(ctx, field)
case "Digest":
return ec.fieldContext_Referrer_Digest(ctx, field)
case "Annotations":
return ec.fieldContext_Referrer_Annotations(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type Referrer", field.Name)
},
}
return fc, nil
}
func (ec *executionContext) _PackageInfo_Name(ctx context.Context, field graphql.CollectedField, obj *PackageInfo) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_PackageInfo_Name(ctx, field)
if err != nil {
@@ -4675,6 +4809,8 @@ func (ec *executionContext) fieldContext_PaginatedImagesResult_Results(ctx conte
return ec.fieldContext_ImageSummary_Authors(ctx, field)
case "Vulnerabilities":
return ec.fieldContext_ImageSummary_Vulnerabilities(ctx, field)
case "Referrers":
return ec.fieldContext_ImageSummary_Referrers(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type ImageSummary", field.Name)
},
@@ -5557,6 +5693,8 @@ func (ec *executionContext) fieldContext_Query_Image(ctx context.Context, field
return ec.fieldContext_ImageSummary_Authors(ctx, field)
case "Vulnerabilities":
return ec.fieldContext_ImageSummary_Vulnerabilities(ctx, field)
case "Referrers":
return ec.fieldContext_ImageSummary_Referrers(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type ImageSummary", field.Name)
},
@@ -6052,6 +6190,8 @@ func (ec *executionContext) fieldContext_RepoInfo_Images(ctx context.Context, fi
return ec.fieldContext_ImageSummary_Authors(ctx, field)
case "Vulnerabilities":
return ec.fieldContext_ImageSummary_Vulnerabilities(ctx, field)
case "Referrers":
return ec.fieldContext_ImageSummary_Referrers(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type ImageSummary", field.Name)
},
@@ -6446,6 +6586,8 @@ func (ec *executionContext) fieldContext_RepoSummary_NewestImage(ctx context.Con
return ec.fieldContext_ImageSummary_Authors(ctx, field)
case "Vulnerabilities":
return ec.fieldContext_ImageSummary_Vulnerabilities(ctx, field)
case "Referrers":
return ec.fieldContext_ImageSummary_Referrers(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type ImageSummary", field.Name)
},
@@ -8745,6 +8887,10 @@ func (ec *executionContext) _ImageSummary(ctx context.Context, sel ast.Selection
out.Values[i] = ec._ImageSummary_Vulnerabilities(ctx, field, obj)
case "Referrers":
out.Values[i] = ec._ImageSummary_Referrers(ctx, field, obj)
default:
panic("unknown field " + strconv.Quote(field.Name))
}
@@ -8893,6 +9039,10 @@ func (ec *executionContext) _ManifestSummary(ctx context.Context, sel ast.Select
out.Values[i] = ec._ManifestSummary_Vulnerabilities(ctx, field, obj)
case "Referrers":
out.Values[i] = ec._ManifestSummary_Referrers(ctx, field, obj)
default:
panic("unknown field " + strconv.Quote(field.Name))
}
@@ -10777,6 +10927,47 @@ func (ec *executionContext) marshalOPlatform2ᚖzotregistryᚗioᚋzotᚋpkgᚋe
return ec._Platform(ctx, sel, v)
}
func (ec *executionContext) marshalOReferrer2ᚕᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐReferrer(ctx context.Context, sel ast.SelectionSet, v []*Referrer) graphql.Marshaler {
if v == nil {
return graphql.Null
}
ret := make(graphql.Array, len(v))
var wg sync.WaitGroup
isLen1 := len(v) == 1
if !isLen1 {
wg.Add(len(v))
}
for i := range v {
i := i
fc := &graphql.FieldContext{
Index: &i,
Result: &v[i],
}
ctx := graphql.WithFieldContext(ctx, fc)
f := func(i int) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = nil
}
}()
if !isLen1 {
defer wg.Done()
}
ret[i] = ec.marshalOReferrer2ᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐReferrer(ctx, sel, v[i])
}
if isLen1 {
f(i)
} else {
go f(i)
}
}
wg.Wait()
return ret
}
func (ec *executionContext) marshalOReferrer2ᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐReferrer(ctx context.Context, sel ast.SelectionSet, v *Referrer) graphql.Marshaler {
if v == nil {
return graphql.Null
@@ -122,6 +122,8 @@ type ImageSummary struct {
Authors *string `json:"Authors"`
// Short summary of the identified CVEs
Vulnerabilities *ImageVulnerabilitySummary `json:"Vulnerabilities"`
// Information about objects that reference this image
Referrers []*Referrer `json:"Referrers"`
}
// Contains summary of vulnerabilities found in a specific image
@@ -171,6 +173,8 @@ type ManifestSummary struct {
History []*LayerHistory `json:"History"`
// Short summary of the identified CVEs
Vulnerabilities *ImageVulnerabilitySummary `json:"Vulnerabilities"`
// Information about objects that reference this image
Referrers []*Referrer `json:"Referrers"`
}
// Contains the name of the package, the current installed version and the version where the CVE was fixed
+1 -1
View File
@@ -1200,7 +1200,7 @@ func getReferrers(repoDB repodb.RepoDB, repo string, referredDigest string, arti
referredDigest, err)
}
referrers, err := repoDB.GetFilteredReferrersInfo(repo, refDigest, artifactTypes)
referrers, err := repoDB.GetReferrersInfo(repo, refDigest, artifactTypes)
if err != nil {
return nil, err
}
+2 -2
View File
@@ -1374,7 +1374,7 @@ func TestGetReferrers(t *testing.T) {
Convey("GetReferrers returns error", func() {
testLogger := log.NewLogger("debug", "")
mockedStore := mocks.RepoDBMock{
GetFilteredReferrersInfoFn: func(repo string, referredDigest godigest.Digest, artifactTypes []string,
GetReferrersInfoFn: func(repo string, referredDigest godigest.Digest, artifactTypes []string,
) ([]repodb.ReferrerInfo, error) {
return nil, ErrTestError
},
@@ -1396,7 +1396,7 @@ func TestGetReferrers(t *testing.T) {
},
}
mockedStore := mocks.RepoDBMock{
GetFilteredReferrersInfoFn: func(repo string, referredDigest godigest.Digest, artifactTypes []string,
GetReferrersInfoFn: func(repo string, referredDigest godigest.Digest, artifactTypes []string,
) ([]repodb.ReferrerInfo, error) {
return []repodb.ReferrerInfo{
{
+8
View File
@@ -184,6 +184,10 @@ type ImageSummary {
Short summary of the identified CVEs
"""
Vulnerabilities: ImageVulnerabilitySummary
"""
Information about objects that reference this image
"""
Referrers: [Referrer]
}
"""
Details about a specific version of an image for a certain operating system and architecture.
@@ -226,6 +230,10 @@ type ManifestSummary {
Short summary of the identified CVEs
"""
Vulnerabilities: ImageVulnerabilitySummary
"""
Information about objects that reference this image
"""
Referrers: [Referrer]
}
"""