mirror of
https://github.com/project-zot/zot.git
synced 2024-12-16 21:56:37 -05:00
Enrich ImageSummary with a new field representing image History
Closing #748 Signed-off-by: Alex Stan <alexandrustan96@yahoo.ro>
This commit is contained in:
parent
7804ba7ce0
commit
42c947fa03
6 changed files with 1096 additions and 27 deletions
|
@ -18,6 +18,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/image-spec/specs-go"
|
||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/sigstore/cosign/cmd/cosign/cli/generate"
|
||||
"github.com/sigstore/cosign/cmd/cosign/cli/options"
|
||||
|
@ -29,6 +30,7 @@ import (
|
|||
"zotregistry.io/zot/pkg/api/constants"
|
||||
extconf "zotregistry.io/zot/pkg/extensions/config"
|
||||
"zotregistry.io/zot/pkg/extensions/monitoring"
|
||||
"zotregistry.io/zot/pkg/extensions/search"
|
||||
"zotregistry.io/zot/pkg/extensions/search/common"
|
||||
"zotregistry.io/zot/pkg/log"
|
||||
"zotregistry.io/zot/pkg/storage"
|
||||
|
@ -56,6 +58,15 @@ type RepoWithNewestImageResponse struct {
|
|||
Errors []ErrorGQL `json:"errors"`
|
||||
}
|
||||
|
||||
type ImageListResponse struct {
|
||||
ImageList ImageList `json:"data"`
|
||||
Errors []ErrorGQL `json:"errors"`
|
||||
}
|
||||
|
||||
type ImageList struct {
|
||||
SummaryList []ImageSummary `json:"imageList"`
|
||||
}
|
||||
|
||||
type ExpandedRepoInfoResp struct {
|
||||
ExpandedRepoInfo ExpandedRepoInfo `json:"data"`
|
||||
Errors []ErrorGQL `json:"errors"`
|
||||
|
@ -76,14 +87,29 @@ type GlobalSearch struct {
|
|||
}
|
||||
|
||||
type ImageSummary struct {
|
||||
RepoName string `json:"repoName"`
|
||||
Tag string `json:"tag"`
|
||||
LastUpdated time.Time `json:"lastUpdated"`
|
||||
Size string `json:"size"`
|
||||
Platform OsArch `json:"platform"`
|
||||
Vendor string `json:"vendor"`
|
||||
Score int `json:"score"`
|
||||
IsSigned bool `json:"isSigned"`
|
||||
RepoName string `json:"repoName"`
|
||||
Tag string `json:"tag"`
|
||||
LastUpdated time.Time `json:"lastUpdated"`
|
||||
Size string `json:"size"`
|
||||
Platform OsArch `json:"platform"`
|
||||
Vendor string `json:"vendor"`
|
||||
Score int `json:"score"`
|
||||
IsSigned bool `json:"isSigned"`
|
||||
History []LayerHistory `json:"history"`
|
||||
Layers []LayerSummary `json:"layers"`
|
||||
}
|
||||
|
||||
type LayerHistory struct {
|
||||
Layer LayerSummary `json:"layer"`
|
||||
HistoryDescription HistoryDescription `json:"historyDescription"`
|
||||
}
|
||||
|
||||
type HistoryDescription struct {
|
||||
Created time.Time `json:"created"`
|
||||
CreatedBy string `json:"createdBy"`
|
||||
Author string `json:"author"`
|
||||
Comment string `json:"comment"`
|
||||
EmptyLayer bool `json:"emptyLayer"`
|
||||
}
|
||||
|
||||
type RepoSummary struct {
|
||||
|
@ -1163,6 +1189,301 @@ func TestGlobalSearch(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestImageList(t *testing.T) {
|
||||
Convey("Test ImageList", t, func() {
|
||||
subpath := "/a"
|
||||
|
||||
err := testSetup(t, subpath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
port := GetFreePort()
|
||||
baseURL := GetBaseURL(port)
|
||||
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
conf.Storage.RootDirectory = rootDir
|
||||
defaultVal := true
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: &extconf.SearchConfig{Enable: &defaultVal},
|
||||
}
|
||||
|
||||
conf.Extensions.Search.CVE = nil
|
||||
|
||||
ctlr := api.NewController(conf)
|
||||
|
||||
go startServer(ctlr)
|
||||
defer stopServer(ctlr)
|
||||
WaitTillServerReady(baseURL)
|
||||
|
||||
imageStore := ctlr.StoreController.DefaultStore
|
||||
|
||||
repos, err := imageStore.GetRepositories()
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
tags, err := imageStore.GetImageTags(repos[0])
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
buf, _, _, err := imageStore.GetImageManifest(repos[0], tags[0])
|
||||
So(err, ShouldBeNil)
|
||||
var imageManifest ispec.Manifest
|
||||
err = json.Unmarshal(buf, &imageManifest)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
var imageConfigInfo ispec.Image
|
||||
imageConfigBuf, err := imageStore.GetBlobContent(repos[0], imageManifest.Config.Digest.String())
|
||||
So(err, ShouldBeNil)
|
||||
err = json.Unmarshal(imageConfigBuf, &imageConfigInfo)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
query := fmt.Sprintf(`{
|
||||
ImageList(repo:"%s"){
|
||||
History{
|
||||
HistoryDescription{
|
||||
Author
|
||||
Comment
|
||||
Created
|
||||
CreatedBy
|
||||
EmptyLayer
|
||||
},
|
||||
Layer{
|
||||
Digest
|
||||
Size
|
||||
}
|
||||
}
|
||||
}
|
||||
}`, repos[0])
|
||||
|
||||
resp, err := resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(query))
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
So(resp, ShouldNotBeNil)
|
||||
|
||||
var responseStruct ImageListResponse
|
||||
err = json.Unmarshal(resp.Body(), &responseStruct)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(len(responseStruct.ImageList.SummaryList[0].History), ShouldEqual, len(imageConfigInfo.History))
|
||||
})
|
||||
|
||||
Convey("Test ImageSummary retuned by ImageList when getting tags timestamp info fails", t, func() {
|
||||
invalid := "test"
|
||||
tempDir := t.TempDir()
|
||||
port := GetFreePort()
|
||||
baseURL := GetBaseURL(port)
|
||||
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
conf.Storage.RootDirectory = tempDir
|
||||
defaultVal := true
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: &extconf.SearchConfig{Enable: &defaultVal},
|
||||
}
|
||||
|
||||
conf.Extensions.Search.CVE = nil
|
||||
|
||||
ctlr := api.NewController(conf)
|
||||
|
||||
go startServer(ctlr)
|
||||
defer stopServer(ctlr)
|
||||
WaitTillServerReady(baseURL)
|
||||
|
||||
config := ispec.Image{
|
||||
Architecture: "amd64",
|
||||
OS: "linux",
|
||||
RootFS: ispec.RootFS{
|
||||
Type: "layers",
|
||||
DiffIDs: []digest.Digest{},
|
||||
},
|
||||
Author: "ZotUser",
|
||||
History: []ispec.History{},
|
||||
}
|
||||
|
||||
configBlob, err := json.Marshal(config)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
configDigest := digest.FromBytes(configBlob)
|
||||
layerDigest := digest.FromString(invalid)
|
||||
layerblob := []byte(invalid)
|
||||
schemaVersion := 2
|
||||
ispecManifest := ispec.Manifest{
|
||||
Versioned: specs.Versioned{
|
||||
SchemaVersion: schemaVersion,
|
||||
},
|
||||
Config: ispec.Descriptor{
|
||||
MediaType: "application/vnd.oci.image.config.v1+json",
|
||||
Digest: configDigest,
|
||||
Size: int64(len(configBlob)),
|
||||
},
|
||||
Layers: []ispec.Descriptor{ // just 1 layer in manifest
|
||||
{
|
||||
MediaType: "application/vnd.oci.image.layer.v1.tar",
|
||||
Digest: layerDigest,
|
||||
Size: int64(len(layerblob)),
|
||||
},
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
ispec.AnnotationRefName: "1.0",
|
||||
},
|
||||
}
|
||||
|
||||
err = UploadImage(
|
||||
Image{
|
||||
Manifest: ispecManifest,
|
||||
Config: config,
|
||||
Layers: [][]byte{
|
||||
layerblob,
|
||||
},
|
||||
Tag: "0.0.1",
|
||||
},
|
||||
baseURL,
|
||||
invalid,
|
||||
)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
configPath := path.Join(conf.Storage.RootDirectory, invalid, "blobs",
|
||||
configDigest.Algorithm().String(), configDigest.Encoded())
|
||||
|
||||
err = os.Remove(configPath)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
query := fmt.Sprintf(`{
|
||||
ImageList(repo:"%s"){
|
||||
History{
|
||||
HistoryDescription{
|
||||
Author
|
||||
Comment
|
||||
Created
|
||||
CreatedBy
|
||||
EmptyLayer
|
||||
},
|
||||
Layer{
|
||||
Digest
|
||||
Size
|
||||
}
|
||||
}
|
||||
}
|
||||
}`, invalid)
|
||||
|
||||
resp, err := resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(query))
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
So(resp, ShouldNotBeNil)
|
||||
|
||||
var responseStruct ImageListResponse
|
||||
err = json.Unmarshal(resp.Body(), &responseStruct)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(responseStruct.ImageList.SummaryList), ShouldBeZeroValue)
|
||||
})
|
||||
}
|
||||
|
||||
func TestBuildImageInfo(t *testing.T) {
|
||||
Convey("Check image summary when layer count does not match history", t, func() {
|
||||
invalid := "invalid"
|
||||
|
||||
port := GetFreePort()
|
||||
baseURL := GetBaseURL(port)
|
||||
rootDir = t.TempDir()
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
conf.Storage.RootDirectory = rootDir
|
||||
defaultVal := true
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: &extconf.SearchConfig{Enable: &defaultVal},
|
||||
}
|
||||
|
||||
conf.Extensions.Search.CVE = nil
|
||||
|
||||
ctlr := api.NewController(conf)
|
||||
|
||||
go startServer(ctlr)
|
||||
defer stopServer(ctlr)
|
||||
WaitTillServerReady(baseURL)
|
||||
|
||||
olu := &common.BaseOciLayoutUtils{
|
||||
StoreController: ctlr.StoreController,
|
||||
Log: ctlr.Log,
|
||||
}
|
||||
|
||||
config := ispec.Image{
|
||||
Architecture: "amd64",
|
||||
OS: "linux",
|
||||
RootFS: ispec.RootFS{
|
||||
Type: "layers",
|
||||
DiffIDs: []digest.Digest{},
|
||||
},
|
||||
Author: "ZotUser",
|
||||
History: []ispec.History{ // should contain 3 elements, 2 of which corresponding to layers
|
||||
{
|
||||
EmptyLayer: false,
|
||||
},
|
||||
{
|
||||
EmptyLayer: false,
|
||||
},
|
||||
{
|
||||
EmptyLayer: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
configBlob, err := json.Marshal(config)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
configDigest := digest.FromBytes(configBlob)
|
||||
layerDigest := digest.FromString(invalid)
|
||||
layerblob := []byte(invalid)
|
||||
schemaVersion := 2
|
||||
ispecManifest := ispec.Manifest{
|
||||
Versioned: specs.Versioned{
|
||||
SchemaVersion: schemaVersion,
|
||||
},
|
||||
Config: ispec.Descriptor{
|
||||
MediaType: "application/vnd.oci.image.config.v1+json",
|
||||
Digest: configDigest,
|
||||
Size: int64(len(configBlob)),
|
||||
},
|
||||
Layers: []ispec.Descriptor{ // just 1 layer in manifest
|
||||
{
|
||||
MediaType: "application/vnd.oci.image.layer.v1.tar",
|
||||
Digest: layerDigest,
|
||||
Size: int64(len(layerblob)),
|
||||
},
|
||||
},
|
||||
}
|
||||
manifestLayersSize := ispecManifest.Layers[0].Size
|
||||
manifestBlob, err := json.Marshal(ispecManifest)
|
||||
So(err, ShouldBeNil)
|
||||
manifestDigest := digest.FromBytes(manifestBlob)
|
||||
err = UploadImage(
|
||||
Image{
|
||||
Manifest: ispecManifest,
|
||||
Config: config,
|
||||
Layers: [][]byte{
|
||||
layerblob,
|
||||
},
|
||||
Tag: "0.0.1",
|
||||
},
|
||||
baseURL,
|
||||
invalid,
|
||||
)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
manifest, err := olu.GetImageBlobManifest(invalid, manifestDigest)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
imageConfig, err := olu.GetImageConfigInfo(invalid, manifestDigest)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
imageSummary := search.BuildImageInfo(invalid, invalid, manifestDigest, manifest, imageConfig)
|
||||
|
||||
So(len(imageSummary.Layers), ShouldEqual, len(manifest.Layers))
|
||||
imageSummaryLayerSize, err := strconv.Atoi(*imageSummary.Size)
|
||||
So(err, ShouldBeNil)
|
||||
So(imageSummaryLayerSize, ShouldEqual, manifestLayersSize)
|
||||
})
|
||||
}
|
||||
|
||||
func TestBaseOciLayoutUtils(t *testing.T) {
|
||||
manifestDigest := "sha256:adf3bb6cc81f8bd6a9d5233be5f0c1a4f1e3ed1cf5bbdfad7708cc8d4099b741"
|
||||
|
||||
|
|
|
@ -62,12 +62,21 @@ type ComplexityRoot struct {
|
|||
Repos func(childComplexity int) int
|
||||
}
|
||||
|
||||
HistoryDescription struct {
|
||||
Author func(childComplexity int) int
|
||||
Comment func(childComplexity int) int
|
||||
Created func(childComplexity int) int
|
||||
CreatedBy func(childComplexity int) int
|
||||
EmptyLayer func(childComplexity int) int
|
||||
}
|
||||
|
||||
ImageSummary struct {
|
||||
ConfigDigest func(childComplexity int) int
|
||||
Description func(childComplexity int) int
|
||||
Digest func(childComplexity int) int
|
||||
Documentation func(childComplexity int) int
|
||||
DownloadCount func(childComplexity int) int
|
||||
History func(childComplexity int) int
|
||||
IsSigned func(childComplexity int) int
|
||||
Labels func(childComplexity int) int
|
||||
LastUpdated func(childComplexity int) int
|
||||
|
@ -83,6 +92,11 @@ type ComplexityRoot struct {
|
|||
Vendor func(childComplexity int) int
|
||||
}
|
||||
|
||||
LayerHistory struct {
|
||||
HistoryDescription func(childComplexity int) int
|
||||
Layer func(childComplexity int) int
|
||||
}
|
||||
|
||||
LayerSummary struct {
|
||||
Digest func(childComplexity int) int
|
||||
Score func(childComplexity int) int
|
||||
|
@ -226,6 +240,41 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||
|
||||
return e.complexity.GlobalSearchResult.Repos(childComplexity), true
|
||||
|
||||
case "HistoryDescription.Author":
|
||||
if e.complexity.HistoryDescription.Author == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.HistoryDescription.Author(childComplexity), true
|
||||
|
||||
case "HistoryDescription.Comment":
|
||||
if e.complexity.HistoryDescription.Comment == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.HistoryDescription.Comment(childComplexity), true
|
||||
|
||||
case "HistoryDescription.Created":
|
||||
if e.complexity.HistoryDescription.Created == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.HistoryDescription.Created(childComplexity), true
|
||||
|
||||
case "HistoryDescription.CreatedBy":
|
||||
if e.complexity.HistoryDescription.CreatedBy == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.HistoryDescription.CreatedBy(childComplexity), true
|
||||
|
||||
case "HistoryDescription.EmptyLayer":
|
||||
if e.complexity.HistoryDescription.EmptyLayer == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.HistoryDescription.EmptyLayer(childComplexity), true
|
||||
|
||||
case "ImageSummary.ConfigDigest":
|
||||
if e.complexity.ImageSummary.ConfigDigest == nil {
|
||||
break
|
||||
|
@ -261,6 +310,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||
|
||||
return e.complexity.ImageSummary.DownloadCount(childComplexity), true
|
||||
|
||||
case "ImageSummary.History":
|
||||
if e.complexity.ImageSummary.History == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.ImageSummary.History(childComplexity), true
|
||||
|
||||
case "ImageSummary.IsSigned":
|
||||
if e.complexity.ImageSummary.IsSigned == nil {
|
||||
break
|
||||
|
@ -352,6 +408,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||
|
||||
return e.complexity.ImageSummary.Vendor(childComplexity), true
|
||||
|
||||
case "LayerHistory.HistoryDescription":
|
||||
if e.complexity.LayerHistory.HistoryDescription == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.LayerHistory.HistoryDescription(childComplexity), true
|
||||
|
||||
case "LayerHistory.Layer":
|
||||
if e.complexity.LayerHistory.Layer == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.LayerHistory.Layer(childComplexity), true
|
||||
|
||||
case "LayerSummary.Digest":
|
||||
if e.complexity.LayerSummary.Digest == nil {
|
||||
break
|
||||
|
@ -690,6 +760,7 @@ type ImageSummary {
|
|||
Title: String
|
||||
Source: String
|
||||
Documentation: String
|
||||
History: [LayerHistory]
|
||||
}
|
||||
|
||||
# Brief on a specific repo to be used in queries returning a list of repos
|
||||
|
@ -714,6 +785,31 @@ type LayerSummary {
|
|||
Score: Int
|
||||
}
|
||||
|
||||
type HistoryDescription {
|
||||
Created: Time
|
||||
"""
|
||||
CreatedBy is the command which created the layer.
|
||||
"""
|
||||
CreatedBy: String
|
||||
"""
|
||||
Author is the author of the build point.
|
||||
"""
|
||||
Author: String
|
||||
"""
|
||||
Comment is a custom message set when creating the layer.
|
||||
"""
|
||||
Comment: String
|
||||
"""
|
||||
EmptyLayer is used to mark if the history item created a filesystem diff.
|
||||
"""
|
||||
EmptyLayer: Boolean
|
||||
}
|
||||
|
||||
type LayerHistory {
|
||||
Layer: LayerSummary
|
||||
HistoryDescription: HistoryDescription
|
||||
}
|
||||
|
||||
type OsArch {
|
||||
Os: String
|
||||
Arch: String
|
||||
|
@ -1283,6 +1379,8 @@ func (ec *executionContext) fieldContext_GlobalSearchResult_Images(ctx context.C
|
|||
return ec.fieldContext_ImageSummary_Source(ctx, field)
|
||||
case "Documentation":
|
||||
return ec.fieldContext_ImageSummary_Documentation(ctx, field)
|
||||
case "History":
|
||||
return ec.fieldContext_ImageSummary_History(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type ImageSummary", field.Name)
|
||||
},
|
||||
|
@ -1402,6 +1500,211 @@ func (ec *executionContext) fieldContext_GlobalSearchResult_Layers(ctx context.C
|
|||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _HistoryDescription_Created(ctx context.Context, field graphql.CollectedField, obj *HistoryDescription) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_HistoryDescription_Created(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.Created, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*time.Time)
|
||||
fc.Result = res
|
||||
return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_HistoryDescription_Created(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "HistoryDescription",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type Time does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _HistoryDescription_CreatedBy(ctx context.Context, field graphql.CollectedField, obj *HistoryDescription) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_HistoryDescription_CreatedBy(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.CreatedBy, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*string)
|
||||
fc.Result = res
|
||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_HistoryDescription_CreatedBy(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "HistoryDescription",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type String does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _HistoryDescription_Author(ctx context.Context, field graphql.CollectedField, obj *HistoryDescription) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_HistoryDescription_Author(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.Author, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*string)
|
||||
fc.Result = res
|
||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_HistoryDescription_Author(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "HistoryDescription",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type String does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _HistoryDescription_Comment(ctx context.Context, field graphql.CollectedField, obj *HistoryDescription) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_HistoryDescription_Comment(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.Comment, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*string)
|
||||
fc.Result = res
|
||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_HistoryDescription_Comment(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "HistoryDescription",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type String does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _HistoryDescription_EmptyLayer(ctx context.Context, field graphql.CollectedField, obj *HistoryDescription) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_HistoryDescription_EmptyLayer(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.EmptyLayer, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*bool)
|
||||
fc.Result = res
|
||||
return ec.marshalOBoolean2ᚖbool(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_HistoryDescription_EmptyLayer(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "HistoryDescription",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type Boolean does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _ImageSummary_RepoName(ctx context.Context, field graphql.CollectedField, obj *ImageSummary) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_ImageSummary_RepoName(ctx, field)
|
||||
if err != nil {
|
||||
|
@ -2154,6 +2457,155 @@ func (ec *executionContext) fieldContext_ImageSummary_Documentation(ctx context.
|
|||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _ImageSummary_History(ctx context.Context, field graphql.CollectedField, obj *ImageSummary) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_ImageSummary_History(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.History, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.([]*LayerHistory)
|
||||
fc.Result = res
|
||||
return ec.marshalOLayerHistory2ᚕᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐLayerHistory(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_ImageSummary_History(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 "Layer":
|
||||
return ec.fieldContext_LayerHistory_Layer(ctx, field)
|
||||
case "HistoryDescription":
|
||||
return ec.fieldContext_LayerHistory_HistoryDescription(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type LayerHistory", field.Name)
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _LayerHistory_Layer(ctx context.Context, field graphql.CollectedField, obj *LayerHistory) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_LayerHistory_Layer(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.Layer, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*LayerSummary)
|
||||
fc.Result = res
|
||||
return ec.marshalOLayerSummary2ᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐLayerSummary(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_LayerHistory_Layer(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "LayerHistory",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
switch field.Name {
|
||||
case "Size":
|
||||
return ec.fieldContext_LayerSummary_Size(ctx, field)
|
||||
case "Digest":
|
||||
return ec.fieldContext_LayerSummary_Digest(ctx, field)
|
||||
case "Score":
|
||||
return ec.fieldContext_LayerSummary_Score(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type LayerSummary", field.Name)
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _LayerHistory_HistoryDescription(ctx context.Context, field graphql.CollectedField, obj *LayerHistory) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_LayerHistory_HistoryDescription(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.HistoryDescription, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*HistoryDescription)
|
||||
fc.Result = res
|
||||
return ec.marshalOHistoryDescription2ᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐHistoryDescription(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_LayerHistory_HistoryDescription(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "LayerHistory",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
switch field.Name {
|
||||
case "Created":
|
||||
return ec.fieldContext_HistoryDescription_Created(ctx, field)
|
||||
case "CreatedBy":
|
||||
return ec.fieldContext_HistoryDescription_CreatedBy(ctx, field)
|
||||
case "Author":
|
||||
return ec.fieldContext_HistoryDescription_Author(ctx, field)
|
||||
case "Comment":
|
||||
return ec.fieldContext_HistoryDescription_Comment(ctx, field)
|
||||
case "EmptyLayer":
|
||||
return ec.fieldContext_HistoryDescription_EmptyLayer(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type HistoryDescription", field.Name)
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _LayerSummary_Size(ctx context.Context, field graphql.CollectedField, obj *LayerSummary) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_LayerSummary_Size(ctx, field)
|
||||
if err != nil {
|
||||
|
@ -2615,6 +3067,8 @@ func (ec *executionContext) fieldContext_Query_ImageListForCVE(ctx context.Conte
|
|||
return ec.fieldContext_ImageSummary_Source(ctx, field)
|
||||
case "Documentation":
|
||||
return ec.fieldContext_ImageSummary_Documentation(ctx, field)
|
||||
case "History":
|
||||
return ec.fieldContext_ImageSummary_History(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type ImageSummary", field.Name)
|
||||
},
|
||||
|
@ -2705,6 +3159,8 @@ func (ec *executionContext) fieldContext_Query_ImageListWithCVEFixed(ctx context
|
|||
return ec.fieldContext_ImageSummary_Source(ctx, field)
|
||||
case "Documentation":
|
||||
return ec.fieldContext_ImageSummary_Documentation(ctx, field)
|
||||
case "History":
|
||||
return ec.fieldContext_ImageSummary_History(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type ImageSummary", field.Name)
|
||||
},
|
||||
|
@ -2795,6 +3251,8 @@ func (ec *executionContext) fieldContext_Query_ImageListForDigest(ctx context.Co
|
|||
return ec.fieldContext_ImageSummary_Source(ctx, field)
|
||||
case "Documentation":
|
||||
return ec.fieldContext_ImageSummary_Documentation(ctx, field)
|
||||
case "History":
|
||||
return ec.fieldContext_ImageSummary_History(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type ImageSummary", field.Name)
|
||||
},
|
||||
|
@ -2951,6 +3409,8 @@ func (ec *executionContext) fieldContext_Query_ImageList(ctx context.Context, fi
|
|||
return ec.fieldContext_ImageSummary_Source(ctx, field)
|
||||
case "Documentation":
|
||||
return ec.fieldContext_ImageSummary_Documentation(ctx, field)
|
||||
case "History":
|
||||
return ec.fieldContext_ImageSummary_History(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type ImageSummary", field.Name)
|
||||
},
|
||||
|
@ -3294,6 +3754,8 @@ func (ec *executionContext) fieldContext_RepoInfo_Images(ctx context.Context, fi
|
|||
return ec.fieldContext_ImageSummary_Source(ctx, field)
|
||||
case "Documentation":
|
||||
return ec.fieldContext_ImageSummary_Documentation(ctx, field)
|
||||
case "History":
|
||||
return ec.fieldContext_ImageSummary_History(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type ImageSummary", field.Name)
|
||||
},
|
||||
|
@ -3688,6 +4150,8 @@ func (ec *executionContext) fieldContext_RepoSummary_NewestImage(ctx context.Con
|
|||
return ec.fieldContext_ImageSummary_Source(ctx, field)
|
||||
case "Documentation":
|
||||
return ec.fieldContext_ImageSummary_Documentation(ctx, field)
|
||||
case "History":
|
||||
return ec.fieldContext_ImageSummary_History(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type ImageSummary", field.Name)
|
||||
},
|
||||
|
@ -5702,6 +6166,47 @@ func (ec *executionContext) _GlobalSearchResult(ctx context.Context, sel ast.Sel
|
|||
return out
|
||||
}
|
||||
|
||||
var historyDescriptionImplementors = []string{"HistoryDescription"}
|
||||
|
||||
func (ec *executionContext) _HistoryDescription(ctx context.Context, sel ast.SelectionSet, obj *HistoryDescription) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, historyDescriptionImplementors)
|
||||
out := graphql.NewFieldSet(fields)
|
||||
var invalids uint32
|
||||
for i, field := range fields {
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString("HistoryDescription")
|
||||
case "Created":
|
||||
|
||||
out.Values[i] = ec._HistoryDescription_Created(ctx, field, obj)
|
||||
|
||||
case "CreatedBy":
|
||||
|
||||
out.Values[i] = ec._HistoryDescription_CreatedBy(ctx, field, obj)
|
||||
|
||||
case "Author":
|
||||
|
||||
out.Values[i] = ec._HistoryDescription_Author(ctx, field, obj)
|
||||
|
||||
case "Comment":
|
||||
|
||||
out.Values[i] = ec._HistoryDescription_Comment(ctx, field, obj)
|
||||
|
||||
case "EmptyLayer":
|
||||
|
||||
out.Values[i] = ec._HistoryDescription_EmptyLayer(ctx, field, obj)
|
||||
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
}
|
||||
out.Dispatch()
|
||||
if invalids > 0 {
|
||||
return graphql.Null
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
var imageSummaryImplementors = []string{"ImageSummary"}
|
||||
|
||||
func (ec *executionContext) _ImageSummary(ctx context.Context, sel ast.SelectionSet, obj *ImageSummary) graphql.Marshaler {
|
||||
|
@ -5784,6 +6289,39 @@ func (ec *executionContext) _ImageSummary(ctx context.Context, sel ast.Selection
|
|||
|
||||
out.Values[i] = ec._ImageSummary_Documentation(ctx, field, obj)
|
||||
|
||||
case "History":
|
||||
|
||||
out.Values[i] = ec._ImageSummary_History(ctx, field, obj)
|
||||
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
}
|
||||
out.Dispatch()
|
||||
if invalids > 0 {
|
||||
return graphql.Null
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
var layerHistoryImplementors = []string{"LayerHistory"}
|
||||
|
||||
func (ec *executionContext) _LayerHistory(ctx context.Context, sel ast.SelectionSet, obj *LayerHistory) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, layerHistoryImplementors)
|
||||
out := graphql.NewFieldSet(fields)
|
||||
var invalids uint32
|
||||
for i, field := range fields {
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString("LayerHistory")
|
||||
case "Layer":
|
||||
|
||||
out.Values[i] = ec._LayerHistory_Layer(ctx, field, obj)
|
||||
|
||||
case "HistoryDescription":
|
||||
|
||||
out.Values[i] = ec._LayerHistory_HistoryDescription(ctx, field, obj)
|
||||
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
|
@ -6975,6 +7513,13 @@ func (ec *executionContext) marshalOCVE2ᚖzotregistryᚗioᚋzotᚋpkgᚋextens
|
|||
return ec._CVE(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOHistoryDescription2ᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐHistoryDescription(ctx context.Context, sel ast.SelectionSet, v *HistoryDescription) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
return ec._HistoryDescription(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOImageSummary2ᚕᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐImageSummary(ctx context.Context, sel ast.SelectionSet, v []*ImageSummary) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
|
@ -7086,6 +7631,54 @@ func (ec *executionContext) marshalOInt2ᚖint(ctx context.Context, sel ast.Sele
|
|||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOLayerHistory2ᚕᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐLayerHistory(ctx context.Context, sel ast.SelectionSet, v []*LayerHistory) 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.marshalOLayerHistory2ᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐLayerHistory(ctx, sel, v[i])
|
||||
}
|
||||
if isLen1 {
|
||||
f(i)
|
||||
} else {
|
||||
go f(i)
|
||||
}
|
||||
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOLayerHistory2ᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐLayerHistory(ctx context.Context, sel ast.SelectionSet, v *LayerHistory) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
return ec._LayerHistory(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOLayerSummary2ᚕᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐLayerSummary(ctx context.Context, sel ast.SelectionSet, v []*LayerSummary) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
|
|
|
@ -25,6 +25,18 @@ type GlobalSearchResult struct {
|
|||
Layers []*LayerSummary `json:"Layers"`
|
||||
}
|
||||
|
||||
type HistoryDescription struct {
|
||||
Created *time.Time `json:"Created"`
|
||||
// CreatedBy is the command which created the layer.
|
||||
CreatedBy *string `json:"CreatedBy"`
|
||||
// Author is the author of the build point.
|
||||
Author *string `json:"Author"`
|
||||
// Comment is a custom message set when creating the layer.
|
||||
Comment *string `json:"Comment"`
|
||||
// EmptyLayer is used to mark if the history item created a filesystem diff.
|
||||
EmptyLayer *bool `json:"EmptyLayer"`
|
||||
}
|
||||
|
||||
type ImageSummary struct {
|
||||
RepoName *string `json:"RepoName"`
|
||||
Tag *string `json:"Tag"`
|
||||
|
@ -44,6 +56,12 @@ type ImageSummary struct {
|
|||
Title *string `json:"Title"`
|
||||
Source *string `json:"Source"`
|
||||
Documentation *string `json:"Documentation"`
|
||||
History []*LayerHistory `json:"History"`
|
||||
}
|
||||
|
||||
type LayerHistory struct {
|
||||
Layer *LayerSummary `json:"Layer"`
|
||||
HistoryDescription *HistoryDescription `json:"HistoryDescription"`
|
||||
}
|
||||
|
||||
type LayerSummary struct {
|
||||
|
|
|
@ -42,7 +42,10 @@ type cveDetail struct {
|
|||
PackageList []*gql_generated.PackageInfo
|
||||
}
|
||||
|
||||
var ErrBadCtxFormat = errors.New("type assertion failed")
|
||||
var (
|
||||
ErrBadCtxFormat = errors.New("type assertion failed")
|
||||
ErrBadLayerCount = errors.New("manifest: layers count doesn't correspond to config history")
|
||||
)
|
||||
|
||||
// GetResolverConfig ...
|
||||
func GetResolverConfig(log log.Logger, storeController storage.StoreController, enableCVE bool) gql_generated.Config {
|
||||
|
@ -71,6 +74,7 @@ func (r *queryResolver) getImageListForCVE(repoList []string, cvid string, imgSt
|
|||
trivyCtx *cveinfo.TrivyCtx,
|
||||
) ([]*gql_generated.ImageSummary, error) {
|
||||
cveResult := []*gql_generated.ImageSummary{}
|
||||
olu := common.NewBaseOciLayoutUtils(r.storeController, r.log)
|
||||
|
||||
for _, repo := range repoList {
|
||||
r.log.Info().Str("repo", repo).Msg("extracting list of tags available in image repo")
|
||||
|
@ -83,9 +87,15 @@ func (r *queryResolver) getImageListForCVE(repoList []string, cvid string, imgSt
|
|||
}
|
||||
|
||||
for _, imageByCVE := range imageListByCVE {
|
||||
imageConfig, err := olu.GetImageConfigInfo(repo, imageByCVE.Digest)
|
||||
if err != nil {
|
||||
return []*gql_generated.ImageSummary{}, err
|
||||
}
|
||||
|
||||
imageInfo := BuildImageInfo(repo, imageByCVE.Tag, imageByCVE.Digest, imageByCVE.Manifest, imageConfig)
|
||||
|
||||
cveResult = append(
|
||||
cveResult,
|
||||
buildImageInfo(repo, imageByCVE.Tag, imageByCVE.Digest, imageByCVE.Manifest),
|
||||
cveResult, imageInfo,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -95,6 +105,7 @@ func (r *queryResolver) getImageListForCVE(repoList []string, cvid string, imgSt
|
|||
|
||||
func (r *queryResolver) getImageListForDigest(repoList []string, digest string) ([]*gql_generated.ImageSummary, error) {
|
||||
imgResultForDigest := []*gql_generated.ImageSummary{}
|
||||
olu := common.NewBaseOciLayoutUtils(r.storeController, r.log)
|
||||
|
||||
var errResult error
|
||||
|
||||
|
@ -109,7 +120,13 @@ func (r *queryResolver) getImageListForDigest(repoList []string, digest string)
|
|||
}
|
||||
|
||||
for _, imageInfo := range imgTags {
|
||||
imageInfo := buildImageInfo(repo, imageInfo.Tag, imageInfo.Digest, imageInfo.Manifest)
|
||||
imageConfig, err := olu.GetImageConfigInfo(repo, imageInfo.Digest)
|
||||
if err != nil {
|
||||
return []*gql_generated.ImageSummary{}, err
|
||||
}
|
||||
|
||||
imageInfo := BuildImageInfo(repo, imageInfo.Tag, imageInfo.Digest, imageInfo.Manifest, imageConfig)
|
||||
|
||||
imgResultForDigest = append(imgResultForDigest, imageInfo)
|
||||
}
|
||||
}
|
||||
|
@ -526,7 +543,12 @@ func (r *queryResolver) getImageList(store storage.ImageStore, imageName string)
|
|||
return results, err
|
||||
}
|
||||
|
||||
imageInfo := buildImageInfo(repo, tag.Name, digest, manifest)
|
||||
imageConfig, err := layoutUtils.GetImageConfigInfo(repo, digest)
|
||||
if err != nil {
|
||||
return results, err
|
||||
}
|
||||
|
||||
imageInfo := BuildImageInfo(repo, tag.Name, digest, manifest, imageConfig)
|
||||
|
||||
results = append(results, imageInfo)
|
||||
}
|
||||
|
@ -540,36 +562,119 @@ func (r *queryResolver) getImageList(store storage.ImageStore, imageName string)
|
|||
return results, nil
|
||||
}
|
||||
|
||||
func buildImageInfo(repo string, tag string, tagDigest godigest.Digest,
|
||||
manifest v1.Manifest,
|
||||
func BuildImageInfo(repo string, tag string, manifestDigest godigest.Digest,
|
||||
manifest v1.Manifest, imageConfig ispec.Image,
|
||||
) *gql_generated.ImageSummary {
|
||||
layers := []*gql_generated.LayerSummary{}
|
||||
size := int64(0)
|
||||
|
||||
for _, entry := range manifest.Layers {
|
||||
size += entry.Size
|
||||
digest := entry.Digest.Hex
|
||||
layerSize := strconv.FormatInt(entry.Size, 10)
|
||||
log := log.NewLogger("debug", "")
|
||||
|
||||
allHistory := []*gql_generated.LayerHistory{}
|
||||
|
||||
formattedManifestDigest := manifestDigest.Hex()
|
||||
|
||||
history := imageConfig.History
|
||||
if len(history) == 0 {
|
||||
for _, layer := range manifest.Layers {
|
||||
size += layer.Size
|
||||
digest := layer.Digest.Hex
|
||||
layerSize := strconv.FormatInt(layer.Size, 10)
|
||||
|
||||
layer := &gql_generated.LayerSummary{
|
||||
Size: &layerSize,
|
||||
Digest: &digest,
|
||||
}
|
||||
|
||||
layers = append(
|
||||
layers,
|
||||
layer,
|
||||
)
|
||||
|
||||
allHistory = append(allHistory, &gql_generated.LayerHistory{
|
||||
Layer: layer,
|
||||
HistoryDescription: &gql_generated.HistoryDescription{},
|
||||
})
|
||||
}
|
||||
|
||||
formattedSize := strconv.FormatInt(size, 10)
|
||||
|
||||
imageInfo := &gql_generated.ImageSummary{
|
||||
RepoName: &repo,
|
||||
Tag: &tag,
|
||||
Digest: &formattedManifestDigest,
|
||||
ConfigDigest: &manifest.Config.Digest.Hex,
|
||||
Size: &formattedSize,
|
||||
Layers: layers,
|
||||
History: []*gql_generated.LayerHistory{},
|
||||
}
|
||||
|
||||
return imageInfo
|
||||
}
|
||||
|
||||
// iterator over manifest layers
|
||||
var layersIterator int
|
||||
// since we are appending pointers, it is important to iterate with an index over slice
|
||||
for i := range history {
|
||||
allHistory = append(allHistory, &gql_generated.LayerHistory{
|
||||
HistoryDescription: &gql_generated.HistoryDescription{
|
||||
Created: history[i].Created,
|
||||
CreatedBy: &history[i].CreatedBy,
|
||||
Author: &history[i].Author,
|
||||
Comment: &history[i].Comment,
|
||||
EmptyLayer: &history[i].EmptyLayer,
|
||||
},
|
||||
})
|
||||
|
||||
if history[i].EmptyLayer {
|
||||
continue
|
||||
}
|
||||
|
||||
if layersIterator+1 > len(manifest.Layers) {
|
||||
formattedSize := strconv.FormatInt(size, 10)
|
||||
|
||||
log.Error().Err(ErrBadLayerCount).Msg("error on creating layer history for ImageSummary")
|
||||
|
||||
return &gql_generated.ImageSummary{
|
||||
RepoName: &repo,
|
||||
Tag: &tag,
|
||||
Digest: &formattedManifestDigest,
|
||||
ConfigDigest: &manifest.Config.Digest.Hex,
|
||||
Size: &formattedSize,
|
||||
Layers: layers,
|
||||
History: allHistory,
|
||||
}
|
||||
}
|
||||
|
||||
size += manifest.Layers[layersIterator].Size
|
||||
digest := manifest.Layers[layersIterator].Digest.Hex
|
||||
layerSize := strconv.FormatInt(manifest.Layers[layersIterator].Size, 10)
|
||||
|
||||
layer := &gql_generated.LayerSummary{
|
||||
Size: &layerSize,
|
||||
Digest: &digest,
|
||||
}
|
||||
|
||||
layers = append(
|
||||
layers,
|
||||
&gql_generated.LayerSummary{
|
||||
Size: &layerSize,
|
||||
Digest: &digest,
|
||||
},
|
||||
layer,
|
||||
)
|
||||
|
||||
allHistory[i].Layer = layer
|
||||
|
||||
layersIterator++
|
||||
}
|
||||
|
||||
formattedSize := strconv.FormatInt(size, 10)
|
||||
formattedTagDigest := tagDigest.Hex()
|
||||
|
||||
imageInfo := &gql_generated.ImageSummary{
|
||||
RepoName: &repo,
|
||||
Tag: &tag,
|
||||
Digest: &formattedTagDigest,
|
||||
Digest: &formattedManifestDigest,
|
||||
ConfigDigest: &manifest.Config.Digest.Hex,
|
||||
Size: &formattedSize,
|
||||
Layers: layers,
|
||||
History: allHistory,
|
||||
}
|
||||
|
||||
return imageInfo
|
||||
|
|
|
@ -53,6 +53,7 @@ type ImageSummary {
|
|||
Title: String
|
||||
Source: String
|
||||
Documentation: String
|
||||
History: [LayerHistory]
|
||||
}
|
||||
|
||||
# Brief on a specific repo to be used in queries returning a list of repos
|
||||
|
@ -77,6 +78,31 @@ type LayerSummary {
|
|||
Score: Int
|
||||
}
|
||||
|
||||
type HistoryDescription {
|
||||
Created: Time
|
||||
"""
|
||||
CreatedBy is the command which created the layer.
|
||||
"""
|
||||
CreatedBy: String
|
||||
"""
|
||||
Author is the author of the build point.
|
||||
"""
|
||||
Author: String
|
||||
"""
|
||||
Comment is a custom message set when creating the layer.
|
||||
"""
|
||||
Comment: String
|
||||
"""
|
||||
EmptyLayer is used to mark if the history item created a filesystem diff.
|
||||
"""
|
||||
EmptyLayer: Boolean
|
||||
}
|
||||
|
||||
type LayerHistory {
|
||||
Layer: LayerSummary
|
||||
HistoryDescription: HistoryDescription
|
||||
}
|
||||
|
||||
type OsArch {
|
||||
Os: String
|
||||
Arch: String
|
||||
|
|
|
@ -158,7 +158,7 @@ func (r *queryResolver) ImageListForCve(ctx context.Context, id string) ([]*gql_
|
|||
func (r *queryResolver) ImageListWithCVEFixed(ctx context.Context, id string, image string) ([]*gql_generated.ImageSummary, error) {
|
||||
tagListForCVE := []*gql_generated.ImageSummary{}
|
||||
|
||||
r.log.Info().Str("image", image).Msg("extracting list of tags available in image")
|
||||
r.log.Info().Str("image", image).Msg("extracting list of tags available in repo")
|
||||
|
||||
tagsInfo, err := r.cveInfo.LayoutUtils.GetImageTagsWithTimestamp(image)
|
||||
if err != nil {
|
||||
|
@ -232,7 +232,13 @@ func (r *queryResolver) ImageListWithCVEFixed(ctx context.Context, id string, im
|
|||
return []*gql_generated.ImageSummary{}, err
|
||||
}
|
||||
|
||||
imageInfo := buildImageInfo(image, tag.Name, digest, manifest)
|
||||
imageConfig, err := r.cveInfo.LayoutUtils.GetImageConfigInfo(image, digest)
|
||||
if err != nil {
|
||||
return []*gql_generated.ImageSummary{}, err
|
||||
}
|
||||
|
||||
imageInfo := BuildImageInfo(image, tag.Name, digest, manifest, imageConfig)
|
||||
|
||||
tagListForCVE = append(tagListForCVE, imageInfo)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue