refactor(metadb): improve UX by speeding up metadb serialize/deserialize (#1842)
Use protocol buffers and update the metadb interface to better suit our search needs Signed-off-by: Ramkumar Chinchani <rchincha@cisco.com> Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Co-authored-by: Ramkumar Chinchani <rchincha@cisco.com>
This commit is contained in:
parent
f34af3cb3f
commit
56ad9e6707
1
.github/workflows/golangci-lint.yaml
vendored
1
.github/workflows/golangci-lint.yaml
vendored
@ -38,6 +38,7 @@ jobs:
|
|||||||
|
|
||||||
# Optional: if set to true then the action don't cache or restore ~/go/pkg.
|
# Optional: if set to true then the action don't cache or restore ~/go/pkg.
|
||||||
# skip-pkg-cache: true
|
# skip-pkg-cache: true
|
||||||
|
# skip-pkg-cache: false
|
||||||
|
|
||||||
# Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
|
# Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
|
||||||
# skip-build-cache: true
|
# skip-build-cache: true
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -18,6 +18,7 @@ pkg/extensions/build/
|
|||||||
hack/
|
hack/
|
||||||
.stacker/
|
.stacker/
|
||||||
oci/
|
oci/
|
||||||
|
!pkg/meta/proto/oci
|
||||||
roots/
|
roots/
|
||||||
bin/
|
bin/
|
||||||
bazel-*
|
bazel-*
|
||||||
|
74
Makefile
74
Makefile
@ -32,6 +32,22 @@ TESTDATA := $(TOP_LEVEL)/test/data
|
|||||||
OS ?= $(shell go env GOOS)
|
OS ?= $(shell go env GOOS)
|
||||||
ARCH ?= $(shell go env GOARCH)
|
ARCH ?= $(shell go env GOARCH)
|
||||||
|
|
||||||
|
PROTOC := $(TOOLSDIR)/bin/protoc
|
||||||
|
PROTOC_VERSION := 24.4
|
||||||
|
GO_PROTOC_VERSION := 1.31.0
|
||||||
|
HOST_OS := $(shell go env GOOS)
|
||||||
|
HOST_ARCH := $(shell go env GOARCH)
|
||||||
|
ifeq ($(HOST_OS),linux)
|
||||||
|
PROTOC_OS := linux
|
||||||
|
else ifeq ($(HOST_OS),darwin)
|
||||||
|
PROTOC_OS := osx
|
||||||
|
endif
|
||||||
|
ifeq ($(HOST_ARCH),amd64)
|
||||||
|
PROTOC_ARCH := x86_64
|
||||||
|
else ifeq ($(HOST_ARCH),arm64)
|
||||||
|
PROTOC_ARCH := aarch_64
|
||||||
|
endif
|
||||||
|
|
||||||
BENCH_OUTPUT ?= stdout
|
BENCH_OUTPUT ?= stdout
|
||||||
ALL_EXTENSIONS = debug,imagetrust,lint,metrics,mgmt,profile,scrub,search,sync,ui,userprefs
|
ALL_EXTENSIONS = debug,imagetrust,lint,metrics,mgmt,profile,scrub,search,sync,ui,userprefs
|
||||||
EXTENSIONS ?= sync,search,scrub,metrics,lint,ui,mgmt,profile,userprefs,imagetrust
|
EXTENSIONS ?= sync,search,scrub,metrics,lint,ui,mgmt,profile,userprefs,imagetrust
|
||||||
@ -97,6 +113,51 @@ build-metadata: $(if $(findstring ui,$(BUILD_LABELS)), ui)
|
|||||||
echo "\n Files: \n"
|
echo "\n Files: \n"
|
||||||
go list -tags $(BUILD_TAGS) -f '{{ join .GoFiles "\n" }}' ./... | sort -u
|
go list -tags $(BUILD_TAGS) -f '{{ join .GoFiles "\n" }}' ./... | sort -u
|
||||||
|
|
||||||
|
.PHONY: gen-protobuf
|
||||||
|
gen-protobuf: check-not-freebds $(PROTOC)
|
||||||
|
$(PROTOC) --experimental_allow_proto3_optional \
|
||||||
|
--proto_path=$(TOP_LEVEL)/pkg/meta/proto \
|
||||||
|
--go_out=$(TOP_LEVEL)/pkg/meta/proto \
|
||||||
|
--go_opt='Moci/oci.proto=./gen' \
|
||||||
|
--go_opt='Mmeta/meta.proto=./gen' \
|
||||||
|
--go_opt='Moci/config.proto=./gen' \
|
||||||
|
--go_opt='Moci/manifest.proto=./gen' \
|
||||||
|
--go_opt='Moci/index.proto=./gen' \
|
||||||
|
--go_opt='Moci/descriptor.proto=./gen' \
|
||||||
|
--go_opt='Moci/versioned.proto=./gen' \
|
||||||
|
$(TOP_LEVEL)/pkg/meta/proto/meta/meta.proto
|
||||||
|
$(PROTOC) --experimental_allow_proto3_optional \
|
||||||
|
--proto_path=$(TOP_LEVEL)/pkg/meta/proto \
|
||||||
|
--go_out=$(TOP_LEVEL)/pkg/meta/proto \
|
||||||
|
--go_opt='Moci/versioned.proto=./gen' \
|
||||||
|
$(TOP_LEVEL)/pkg/meta/proto/oci/versioned.proto
|
||||||
|
$(PROTOC) --experimental_allow_proto3_optional \
|
||||||
|
--proto_path=$(TOP_LEVEL)/pkg/meta/proto \
|
||||||
|
--go_out=$(TOP_LEVEL)/pkg/meta/proto \
|
||||||
|
--go_opt='Moci/descriptor.proto=./gen' \
|
||||||
|
$(TOP_LEVEL)/pkg/meta/proto/oci/descriptor.proto
|
||||||
|
$(PROTOC) --experimental_allow_proto3_optional \
|
||||||
|
--proto_path=$(TOP_LEVEL)/pkg/meta/proto \
|
||||||
|
--go_out=$(TOP_LEVEL)/pkg/meta/proto \
|
||||||
|
--go_opt='Moci/descriptor.proto=./gen' \
|
||||||
|
--go_opt='Moci/versioned.proto=./gen' \
|
||||||
|
--go_opt='Moci/index.proto=./gen' \
|
||||||
|
$(TOP_LEVEL)/pkg/meta/proto/oci/index.proto
|
||||||
|
$(PROTOC) --experimental_allow_proto3_optional \
|
||||||
|
--proto_path=$(TOP_LEVEL)/pkg/meta/proto \
|
||||||
|
--go_out=$(TOP_LEVEL)/pkg/meta/proto \
|
||||||
|
--go_opt='Moci/oci.proto=./gen' \
|
||||||
|
--go_opt='Moci/descriptor.proto=./gen' \
|
||||||
|
--go_opt='Moci/config.proto=./gen' \
|
||||||
|
$(TOP_LEVEL)/pkg/meta/proto/oci/config.proto
|
||||||
|
$(PROTOC) --experimental_allow_proto3_optional \
|
||||||
|
--proto_path=$(TOP_LEVEL)/pkg/meta/proto \
|
||||||
|
--go_out=$(TOP_LEVEL)/pkg/meta/proto \
|
||||||
|
--go_opt='Moci/versioned.proto=./gen' \
|
||||||
|
--go_opt='Moci/descriptor.proto=./gen' \
|
||||||
|
--go_opt='Moci/manifest.proto=./gen' \
|
||||||
|
$(TOP_LEVEL)/pkg/meta/proto/oci/manifest.proto
|
||||||
|
|
||||||
.PHONY: binary-minimal
|
.PHONY: binary-minimal
|
||||||
binary-minimal: EXTENSIONS=
|
binary-minimal: EXTENSIONS=
|
||||||
binary-minimal: modcheck build-metadata
|
binary-minimal: modcheck build-metadata
|
||||||
@ -218,6 +279,13 @@ $(CRICTL):
|
|||||||
mv crictl $(TOOLSDIR)/bin/crictl
|
mv crictl $(TOOLSDIR)/bin/crictl
|
||||||
chmod +x $(TOOLSDIR)/bin/crictl
|
chmod +x $(TOOLSDIR)/bin/crictl
|
||||||
|
|
||||||
|
$(PROTOC):
|
||||||
|
mkdir -p $(TOOLSDIR)/bin
|
||||||
|
curl -Lo protoc.zip https://github.com/protocolbuffers/protobuf/releases/download/v$(PROTOC_VERSION)/protoc-$(PROTOC_VERSION)-$(PROTOC_OS)-$(PROTOC_ARCH).zip
|
||||||
|
unzip -o -d $(TOOLSDIR) protoc.zip bin/protoc
|
||||||
|
rm protoc.zip
|
||||||
|
chmod +x $(PROTOC)
|
||||||
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@v$(GO_PROTOC_VERSION)
|
||||||
|
|
||||||
$(ACTION_VALIDATOR):
|
$(ACTION_VALIDATOR):
|
||||||
mkdir -p $(TOOLSDIR)/bin
|
mkdir -p $(TOOLSDIR)/bin
|
||||||
@ -515,6 +583,12 @@ ifneq ($(shell go env GOOS),linux)
|
|||||||
$(error makefile target can be run only on linux)
|
$(error makefile target can be run only on linux)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
.PHONY: check-not-freebds
|
||||||
|
check-not-freebds:
|
||||||
|
ifneq ($(shell go env GOOS),freebsd)
|
||||||
|
$(error makefile target can't be run on freebsd)
|
||||||
|
endif
|
||||||
|
|
||||||
.PHONY: check-compatibility
|
.PHONY: check-compatibility
|
||||||
check-compatibility:
|
check-compatibility:
|
||||||
ifeq ($(OS),freebsd)
|
ifeq ($(OS),freebsd)
|
||||||
|
@ -6,3 +6,4 @@ ignore:
|
|||||||
- "./pkg/test/mocks/*.go"
|
- "./pkg/test/mocks/*.go"
|
||||||
- "./swagger/*.go"
|
- "./swagger/*.go"
|
||||||
- "./pkg/test/test_http_server.go"
|
- "./pkg/test/test_http_server.go"
|
||||||
|
- "./pkg/meta/proto/gen/*.go"
|
||||||
|
@ -107,8 +107,8 @@ var (
|
|||||||
ErrBadLayerCount = errors.New("manifest: layers count doesn't correspond to config history")
|
ErrBadLayerCount = errors.New("manifest: layers count doesn't correspond to config history")
|
||||||
ErrManifestConflict = errors.New("manifest: multiple manifests found")
|
ErrManifestConflict = errors.New("manifest: multiple manifests found")
|
||||||
ErrManifestMetaNotFound = errors.New("metadb: image metadata not found for given manifest reference")
|
ErrManifestMetaNotFound = errors.New("metadb: image metadata not found for given manifest reference")
|
||||||
ErrManifestDataNotFound = errors.New("metadb: image data not found for given manifest digest")
|
ErrImageMetaNotFound = errors.New("metadb: image meta not found")
|
||||||
ErrIndexDataNotFount = errors.New("metadb: index data not found for given digest")
|
ErrUnexpectedMediaType = errors.New("metadb: got unexpected media type")
|
||||||
ErrRepoMetaNotFound = errors.New("metadb: repo metadata not found for given repo name")
|
ErrRepoMetaNotFound = errors.New("metadb: repo metadata not found for given repo name")
|
||||||
ErrTagMetaNotFound = errors.New("metadb: tag metadata not found for given repo and tag names")
|
ErrTagMetaNotFound = errors.New("metadb: tag metadata not found for given repo and tag names")
|
||||||
ErrTypeAssertionFailed = errors.New("storage: failed DatabaseDriver type assertion")
|
ErrTypeAssertionFailed = errors.New("storage: failed DatabaseDriver type assertion")
|
||||||
@ -163,4 +163,5 @@ var (
|
|||||||
ErrInvalidOutputFormat = errors.New("cli: invalid output format")
|
ErrInvalidOutputFormat = errors.New("cli: invalid output format")
|
||||||
ErrFlagValueUnsupported = errors.New("supported values ")
|
ErrFlagValueUnsupported = errors.New("supported values ")
|
||||||
ErrUnknownSubcommand = errors.New("cli: unknown subcommand")
|
ErrUnknownSubcommand = errors.New("cli: unknown subcommand")
|
||||||
|
ErrMultipleReposSameName = errors.New("test: can't have multiple repos with the same name")
|
||||||
)
|
)
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
"region": "us-east-2",
|
"region": "us-east-2",
|
||||||
"cacheTablename": "ZotBlobTable",
|
"cacheTablename": "ZotBlobTable",
|
||||||
"repoMetaTablename": "ZotRepoMetadataTable",
|
"repoMetaTablename": "ZotRepoMetadataTable",
|
||||||
"manifestDataTablename": "ZotManifestDataTable",
|
"imageMetaTablename": "ZotImageMetaTable",
|
||||||
|
"repoBlobsInfoTablename": "ZotRepoBlobsInfoTable",
|
||||||
"versionTablename": "ZotVersion"
|
"versionTablename": "ZotVersion"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
"region": "us-east-2",
|
"region": "us-east-2",
|
||||||
"cacheTablename": "ZotBlobTable",
|
"cacheTablename": "ZotBlobTable",
|
||||||
"repoMetaTablename": "ZotRepoMetadataTable",
|
"repoMetaTablename": "ZotRepoMetadataTable",
|
||||||
"manifestDataTablename": "ZotManifestDataTable",
|
"imageMetaTablename": "ZotImageMetaTable",
|
||||||
|
"repoBlobsInfoTablename": "ZotRepoBlobsInfoTable",
|
||||||
"userDataTablename": "ZotUserDataTable",
|
"userDataTablename": "ZotUserDataTable",
|
||||||
"versionTablename": "ZotVersion"
|
"versionTablename": "ZotVersion"
|
||||||
}
|
}
|
||||||
|
2
go.mod
2
go.mod
@ -500,7 +500,7 @@ require (
|
|||||||
google.golang.org/appengine v1.6.8 // indirect
|
google.golang.org/appengine v1.6.8 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect
|
google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect
|
||||||
google.golang.org/grpc v1.58.2 // indirect
|
google.golang.org/grpc v1.58.2 // indirect
|
||||||
google.golang.org/protobuf v1.31.0 // indirect
|
google.golang.org/protobuf v1.31.0
|
||||||
gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect
|
gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
|
@ -148,7 +148,8 @@ func TestCreateCacheDatabaseDriver(t *testing.T) {
|
|||||||
"region": "us-east-2",
|
"region": "us-east-2",
|
||||||
"cacheTablename": "BlobTable",
|
"cacheTablename": "BlobTable",
|
||||||
"repoMetaTablename": "RepoMetadataTable",
|
"repoMetaTablename": "RepoMetadataTable",
|
||||||
"manifestDataTablename": "ManifestDataTable",
|
"imageMetaTablename": "ZotImageMetaTable",
|
||||||
|
"repoBlobsInfoTablename": "ZotRepoBlobsInfoTable",
|
||||||
"userDataTablename": "ZotUserDataTable",
|
"userDataTablename": "ZotUserDataTable",
|
||||||
"versionTablename": "Version",
|
"versionTablename": "Version",
|
||||||
}
|
}
|
||||||
@ -163,7 +164,8 @@ func TestCreateCacheDatabaseDriver(t *testing.T) {
|
|||||||
"region": "us-east-2",
|
"region": "us-east-2",
|
||||||
"cacheTablename": "BlobTable",
|
"cacheTablename": "BlobTable",
|
||||||
"repoMetaTablename": "RepoMetadataTable",
|
"repoMetaTablename": "RepoMetadataTable",
|
||||||
"manifestDataTablename": "ManifestDataTable",
|
"imageMetaTablename": "ZotImageMetaTable",
|
||||||
|
"repoBlobsInfoTablename": "ZotRepoBlobsInfoTable",
|
||||||
"userDataTablename": "ZotUserDataTable",
|
"userDataTablename": "ZotUserDataTable",
|
||||||
"versionTablename": "Version",
|
"versionTablename": "Version",
|
||||||
}
|
}
|
||||||
@ -177,7 +179,8 @@ func TestCreateCacheDatabaseDriver(t *testing.T) {
|
|||||||
"region": "us-east-2",
|
"region": "us-east-2",
|
||||||
"cacheTablename": "BlobTable",
|
"cacheTablename": "BlobTable",
|
||||||
"repoMetaTablename": "RepoMetadataTable",
|
"repoMetaTablename": "RepoMetadataTable",
|
||||||
"manifestDataTablename": "ManifestDataTable",
|
"imageMetaTablename": "ZotImageMetaTable",
|
||||||
|
"repoBlobsInfoTablename": "ZotRepoBlobsInfoTable",
|
||||||
"userDataTablename": "ZotUserDataTable",
|
"userDataTablename": "ZotUserDataTable",
|
||||||
"versionTablename": "Version",
|
"versionTablename": "Version",
|
||||||
}
|
}
|
||||||
@ -210,7 +213,8 @@ func TestCreateMetaDBDriver(t *testing.T) {
|
|||||||
"region": "us-east-2",
|
"region": "us-east-2",
|
||||||
"cachetablename": "BlobTable",
|
"cachetablename": "BlobTable",
|
||||||
"repometatablename": "RepoMetadataTable",
|
"repometatablename": "RepoMetadataTable",
|
||||||
"manifestdatatablename": "ManifestDataTable",
|
"imageMetaTablename": "ZotImageMetaTable",
|
||||||
|
"repoBlobsInfoTablename": "ZotRepoBlobsInfoTable",
|
||||||
"userdatatablename": "UserDatatable",
|
"userdatatablename": "UserDatatable",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +227,8 @@ func TestCreateMetaDBDriver(t *testing.T) {
|
|||||||
"region": "us-east-2",
|
"region": "us-east-2",
|
||||||
"cachetablename": "",
|
"cachetablename": "",
|
||||||
"repometatablename": "RepoMetadataTable",
|
"repometatablename": "RepoMetadataTable",
|
||||||
"manifestdatatablename": "ManifestDataTable",
|
"imageMetaTablename": "ZotImageMetaTable",
|
||||||
|
"repoBlobsInfoTablename": "ZotRepoBlobsInfoTable",
|
||||||
"userDataTablename": "ZotUserDataTable",
|
"userDataTablename": "ZotUserDataTable",
|
||||||
"versiontablename": 1,
|
"versiontablename": 1,
|
||||||
}
|
}
|
||||||
@ -237,8 +242,8 @@ func TestCreateMetaDBDriver(t *testing.T) {
|
|||||||
"region": "us-east-2",
|
"region": "us-east-2",
|
||||||
"cachetablename": "test",
|
"cachetablename": "test",
|
||||||
"repometatablename": "RepoMetadataTable",
|
"repometatablename": "RepoMetadataTable",
|
||||||
"manifestdatatablename": "ManifestDataTable",
|
"imagemetatablename": "ZotImageMetaTable",
|
||||||
"indexdatatablename": "IndexDataTable",
|
"repoblobsinfotablename": "ZotRepoBlobsInfoTable",
|
||||||
"userdatatablename": "ZotUserDataTable",
|
"userdatatablename": "ZotUserDataTable",
|
||||||
"apikeytablename": "APIKeyTable",
|
"apikeytablename": "APIKeyTable",
|
||||||
"versiontablename": "1",
|
"versiontablename": "1",
|
||||||
@ -419,8 +424,8 @@ func TestObjectStorageController(t *testing.T) {
|
|||||||
"region": "us-east-2",
|
"region": "us-east-2",
|
||||||
"cachetablename": "test",
|
"cachetablename": "test",
|
||||||
"repometatablename": "RepoMetadataTable",
|
"repometatablename": "RepoMetadataTable",
|
||||||
"manifestdatatablename": "ManifestDataTable",
|
"imagemetatablename": "ZotImageMetaTable",
|
||||||
"indexdatatablename": "IndexDataTable",
|
"repoblobsinfotablename": "ZotRepoBlobsInfoTable",
|
||||||
"userdatatablename": "ZotUserDataTable",
|
"userdatatablename": "ZotUserDataTable",
|
||||||
"apikeytablename": "APIKeyTable1",
|
"apikeytablename": "APIKeyTable1",
|
||||||
"versiontablename": "Version",
|
"versiontablename": "Version",
|
||||||
@ -7773,6 +7778,8 @@ func TestInjectTooManyOpenFiles(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGCSignaturesAndUntaggedManifestsWithMetaDB(t *testing.T) {
|
func TestGCSignaturesAndUntaggedManifestsWithMetaDB(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
Convey("Make controller", t, func() {
|
Convey("Make controller", t, func() {
|
||||||
Convey("Garbage collect signatures without subject and manifests without tags", func(c C) {
|
Convey("Garbage collect signatures without subject and manifests without tags", func(c C) {
|
||||||
repoName := "testrepo" //nolint:goconst
|
repoName := "testrepo" //nolint:goconst
|
||||||
@ -7804,7 +7811,7 @@ func TestGCSignaturesAndUntaggedManifestsWithMetaDB(t *testing.T) {
|
|||||||
ctlr.Config.Storage.Dedupe = false
|
ctlr.Config.Storage.Dedupe = false
|
||||||
|
|
||||||
cm := test.NewControllerManager(ctlr)
|
cm := test.NewControllerManager(ctlr)
|
||||||
cm.StartServer()
|
cm.StartServer() //nolint: contextcheck
|
||||||
cm.WaitServerToBeReady(port)
|
cm.WaitServerToBeReady(port)
|
||||||
defer cm.StopServer()
|
defer cm.StopServer()
|
||||||
|
|
||||||
@ -7835,7 +7842,7 @@ func TestGCSignaturesAndUntaggedManifestsWithMetaDB(t *testing.T) {
|
|||||||
|
|
||||||
// generate a keypair
|
// generate a keypair
|
||||||
os.Setenv("COSIGN_PASSWORD", "")
|
os.Setenv("COSIGN_PASSWORD", "")
|
||||||
err = generate.GenerateKeyPairCmd(context.TODO(), "", "cosign", nil)
|
err = generate.GenerateKeyPairCmd(ctx, "", "cosign", nil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
image := fmt.Sprintf("localhost:%s/%s@%s", port, repoName, digest.String())
|
image := fmt.Sprintf("localhost:%s/%s@%s", port, repoName, digest.String())
|
||||||
@ -7864,7 +7871,7 @@ func TestGCSignaturesAndUntaggedManifestsWithMetaDB(t *testing.T) {
|
|||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// sign the image
|
// sign the image
|
||||||
err = signature.SignWithNotation("good", image, tdir, true)
|
err = signature.SignWithNotation("good", image, tdir, true) //nolint: contextcheck
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// get cosign signature manifest
|
// get cosign signature manifest
|
||||||
@ -7894,7 +7901,7 @@ func TestGCSignaturesAndUntaggedManifestsWithMetaDB(t *testing.T) {
|
|||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// make sure both signatures are stored in repodb
|
// make sure both signatures are stored in repodb
|
||||||
repoMeta, err := ctlr.MetaDB.GetRepoMeta(repoName)
|
repoMeta, err := ctlr.MetaDB.GetRepoMeta(ctx, repoName)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
sigMeta := repoMeta.Signatures[digest.String()]
|
sigMeta := repoMeta.Signatures[digest.String()]
|
||||||
@ -7955,7 +7962,7 @@ func TestGCSignaturesAndUntaggedManifestsWithMetaDB(t *testing.T) {
|
|||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// make sure repoDB reference was added
|
// make sure repoDB reference was added
|
||||||
repoMeta, err := ctlr.MetaDB.GetRepoMeta(repoName)
|
repoMeta, err := ctlr.MetaDB.GetRepoMeta(ctx, repoName)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
_, ok := repoMeta.Referrers[untaggedManifestDigest.String()]
|
_, ok := repoMeta.Referrers[untaggedManifestDigest.String()]
|
||||||
@ -7984,8 +7991,8 @@ func TestGCSignaturesAndUntaggedManifestsWithMetaDB(t *testing.T) {
|
|||||||
err = gc.CleanRepo(repoName)
|
err = gc.CleanRepo(repoName)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// make sure both signatures are removed from repodb and repo reference for untagged is removed
|
// make sure both signatures are removed from metaDB and repo reference for untagged is removed
|
||||||
repoMeta, err = ctlr.MetaDB.GetRepoMeta(repoName)
|
repoMeta, err = ctlr.MetaDB.GetRepoMeta(ctx, repoName)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
sigMeta := repoMeta.Signatures[digest.String()]
|
sigMeta := repoMeta.Signatures[digest.String()]
|
||||||
|
@ -516,7 +516,7 @@ func (rh *RouteHandler) GetManifest(response http.ResponseWriter, request *http.
|
|||||||
}
|
}
|
||||||
|
|
||||||
if rh.c.MetaDB != nil {
|
if rh.c.MetaDB != nil {
|
||||||
err := meta.OnGetManifest(name, reference, content, rh.c.StoreController, rh.c.MetaDB, rh.c.Log)
|
err := meta.OnGetManifest(name, reference, mediaType, content, rh.c.StoreController, rh.c.MetaDB, rh.c.Log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.WriteHeader(http.StatusInternalServerError)
|
response.WriteHeader(http.StatusInternalServerError)
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ package client_test
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -733,7 +732,7 @@ func getMockCveScanner(metaDB mTypes.MetaDB) cveinfo.Scanner {
|
|||||||
imageDir := repo
|
imageDir := repo
|
||||||
inputTag := reference
|
inputTag := reference
|
||||||
|
|
||||||
repoMeta, err := metaDB.GetRepoMeta(imageDir)
|
repoMeta, err := metaDB.GetRepoMeta(context.Background(), imageDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@ -756,19 +755,12 @@ func getMockCveScanner(metaDB mTypes.MetaDB) cveinfo.Scanner {
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
manifestData, err := metaDB.GetManifestData(manifestDigest)
|
manifestData, err := metaDB.GetImageMeta(manifestDigest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var manifestContent ispec.Manifest
|
for _, imageLayer := range manifestData.Manifests[0].Manifest.Layers {
|
||||||
|
|
||||||
err = json.Unmarshal(manifestData.ManifestBlob, &manifestContent)
|
|
||||||
if err != nil {
|
|
||||||
return false, zerr.ErrScanNotSupported
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, imageLayer := range manifestContent.Layers {
|
|
||||||
switch imageLayer.MediaType {
|
switch imageLayer.MediaType {
|
||||||
case ispec.MediaTypeImageLayerGzip, ispec.MediaTypeImageLayer, string(regTypes.DockerLayer):
|
case ispec.MediaTypeImageLayerGzip, ispec.MediaTypeImageLayer, string(regTypes.DockerLayer):
|
||||||
|
|
||||||
|
@ -29,6 +29,12 @@ const (
|
|||||||
ArtifactTypeNotation = "application/vnd.cncf.notary.signature"
|
ArtifactTypeNotation = "application/vnd.cncf.notary.signature"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var cosignTagRule = regexp.MustCompile(`sha256\-.+\.sig`)
|
||||||
|
|
||||||
|
func IsCosignTag(tag string) bool {
|
||||||
|
return cosignTagRule.MatchString(tag)
|
||||||
|
}
|
||||||
|
|
||||||
func Contains[T comparable](elems []T, v T) bool {
|
func Contains[T comparable](elems []T, v T) bool {
|
||||||
for _, s := range elems {
|
for _, s := range elems {
|
||||||
if v == s {
|
if v == s {
|
||||||
|
@ -131,11 +131,11 @@ func TestSignatureUploadAndVerificationAWS(t *testing.T) {
|
|||||||
|
|
||||||
cacheTablename := "BlobTable" + uuid.String()
|
cacheTablename := "BlobTable" + uuid.String()
|
||||||
repoMetaTablename := "RepoMetadataTable" + uuid.String()
|
repoMetaTablename := "RepoMetadataTable" + uuid.String()
|
||||||
manifestDataTablename := "ManifestDataTable" + uuid.String()
|
|
||||||
versionTablename := "Version" + uuid.String()
|
versionTablename := "Version" + uuid.String()
|
||||||
indexDataTablename := "IndexDataTable" + uuid.String()
|
|
||||||
userDataTablename := "UserDataTable" + uuid.String()
|
userDataTablename := "UserDataTable" + uuid.String()
|
||||||
apiKeyTablename := "ApiKeyTable" + uuid.String()
|
apiKeyTablename := "ApiKeyTable" + uuid.String()
|
||||||
|
imageMetaTablename := "imageMetaTable" + uuid.String()
|
||||||
|
repoBlobsInfoTablename := "repoBlobsInfoTable" + uuid.String()
|
||||||
|
|
||||||
cacheDriverParams := map[string]interface{}{
|
cacheDriverParams := map[string]interface{}{
|
||||||
"name": "dynamoDB",
|
"name": "dynamoDB",
|
||||||
@ -143,8 +143,8 @@ func TestSignatureUploadAndVerificationAWS(t *testing.T) {
|
|||||||
"region": "us-east-2",
|
"region": "us-east-2",
|
||||||
"cacheTablename": cacheTablename,
|
"cacheTablename": cacheTablename,
|
||||||
"repoMetaTablename": repoMetaTablename,
|
"repoMetaTablename": repoMetaTablename,
|
||||||
"manifestDataTablename": manifestDataTablename,
|
"imageMetaTablename": imageMetaTablename,
|
||||||
"indexDataTablename": indexDataTablename,
|
"repoBlobsInfoTablename": repoBlobsInfoTablename,
|
||||||
"userDataTablename": userDataTablename,
|
"userDataTablename": userDataTablename,
|
||||||
"apiKeyTablename": apiKeyTablename,
|
"apiKeyTablename": apiKeyTablename,
|
||||||
"versionTablename": versionTablename,
|
"versionTablename": versionTablename,
|
||||||
|
@ -5,7 +5,6 @@ package imagetrust
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go-v2/aws"
|
"github.com/aws/aws-sdk-go-v2/aws"
|
||||||
@ -158,18 +157,13 @@ func IsResourceExistsException(err error) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (imgTrustStore *ImageTrustStore) VerifySignature(
|
func (imgTrustStore *ImageTrustStore) VerifySignature(
|
||||||
signatureType string, rawSignature []byte, sigKey string, manifestDigest godigest.Digest, manifestContent []byte,
|
signatureType string, rawSignature []byte, sigKey string, manifestDigest godigest.Digest, imageMeta mTypes.ImageMeta,
|
||||||
repo string,
|
repo string,
|
||||||
) (string, time.Time, bool, error) {
|
) (string, time.Time, bool, error) {
|
||||||
var manifest ispec.Manifest
|
|
||||||
if err := json.Unmarshal(manifestContent, &manifest); err != nil {
|
|
||||||
return "", time.Time{}, false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
desc := ispec.Descriptor{
|
desc := ispec.Descriptor{
|
||||||
MediaType: manifest.MediaType,
|
MediaType: imageMeta.MediaType,
|
||||||
Digest: manifestDigest,
|
Digest: imageMeta.Digest,
|
||||||
Size: int64(len(manifestContent)),
|
Size: imageMeta.Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
if manifestDigest.String() == "" {
|
if manifestDigest.String() == "" {
|
||||||
@ -190,7 +184,7 @@ func (imgTrustStore *ImageTrustStore) VerifySignature(
|
|||||||
|
|
||||||
func NewTaskGenerator(metaDB mTypes.MetaDB, log log.Logger) scheduler.TaskGenerator {
|
func NewTaskGenerator(metaDB mTypes.MetaDB, log log.Logger) scheduler.TaskGenerator {
|
||||||
return &sigValidityTaskGenerator{
|
return &sigValidityTaskGenerator{
|
||||||
repos: []mTypes.RepoMetadata{},
|
repos: []mTypes.RepoMeta{},
|
||||||
metaDB: metaDB,
|
metaDB: metaDB,
|
||||||
repoIndex: -1,
|
repoIndex: -1,
|
||||||
log: log,
|
log: log,
|
||||||
@ -198,7 +192,7 @@ func NewTaskGenerator(metaDB mTypes.MetaDB, log log.Logger) scheduler.TaskGenera
|
|||||||
}
|
}
|
||||||
|
|
||||||
type sigValidityTaskGenerator struct {
|
type sigValidityTaskGenerator struct {
|
||||||
repos []mTypes.RepoMetadata
|
repos []mTypes.RepoMeta
|
||||||
metaDB mTypes.MetaDB
|
metaDB mTypes.MetaDB
|
||||||
repoIndex int
|
repoIndex int
|
||||||
done bool
|
done bool
|
||||||
@ -209,7 +203,7 @@ func (gen *sigValidityTaskGenerator) Next() (scheduler.Task, error) {
|
|||||||
if len(gen.repos) == 0 {
|
if len(gen.repos) == 0 {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
repos, err := gen.metaDB.GetMultipleRepoMeta(ctx, func(repoMeta mTypes.RepoMetadata) bool {
|
repos, err := gen.metaDB.GetMultipleRepoMeta(ctx, func(repoMeta mTypes.RepoMeta) bool {
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -243,18 +237,18 @@ func (gen *sigValidityTaskGenerator) IsReady() bool {
|
|||||||
func (gen *sigValidityTaskGenerator) Reset() {
|
func (gen *sigValidityTaskGenerator) Reset() {
|
||||||
gen.done = false
|
gen.done = false
|
||||||
gen.repoIndex = -1
|
gen.repoIndex = -1
|
||||||
gen.repos = []mTypes.RepoMetadata{}
|
gen.repos = []mTypes.RepoMeta{}
|
||||||
|
|
||||||
gen.log.Info().Msg("finished resetting task generator for updating signatures validity")
|
gen.log.Info().Msg("finished resetting task generator for updating signatures validity")
|
||||||
}
|
}
|
||||||
|
|
||||||
type validityTask struct {
|
type validityTask struct {
|
||||||
metaDB mTypes.MetaDB
|
metaDB mTypes.MetaDB
|
||||||
repo mTypes.RepoMetadata
|
repo mTypes.RepoMeta
|
||||||
log log.Logger
|
log log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewValidityTask(metaDB mTypes.MetaDB, repo mTypes.RepoMetadata, log log.Logger) *validityTask {
|
func NewValidityTask(metaDB mTypes.MetaDB, repo mTypes.RepoMeta, log log.Logger) *validityTask {
|
||||||
return &validityTask{metaDB, repo, log}
|
return &validityTask{metaDB, repo, log}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
godigest "github.com/opencontainers/go-digest"
|
godigest "github.com/opencontainers/go-digest"
|
||||||
|
|
||||||
|
mTypes "zotregistry.io/zot/pkg/meta/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewLocalImageTrustStore(dir string) (*imageTrustDisabled, error) {
|
func NewLocalImageTrustStore(dir string) (*imageTrustDisabled, error) {
|
||||||
@ -20,7 +22,7 @@ func NewAWSImageTrustStore(region, endpoint string) (*imageTrustDisabled, error)
|
|||||||
type imageTrustDisabled struct{}
|
type imageTrustDisabled struct{}
|
||||||
|
|
||||||
func (imgTrustStore *imageTrustDisabled) VerifySignature(
|
func (imgTrustStore *imageTrustDisabled) VerifySignature(
|
||||||
signatureType string, rawSignature []byte, sigKey string, manifestDigest godigest.Digest, manifestContent []byte,
|
signatureType string, rawSignature []byte, sigKey string, manifestDigest godigest.Digest, imageMeta mTypes.ImageMeta,
|
||||||
repo string,
|
repo string,
|
||||||
) (string, time.Time, bool, error) {
|
) (string, time.Time, bool, error) {
|
||||||
return "", time.Time{}, false, nil
|
return "", time.Time{}, false, nil
|
||||||
|
@ -27,15 +27,13 @@ func TestImageTrust(t *testing.T) {
|
|||||||
|
|
||||||
repo := "repo"
|
repo := "repo"
|
||||||
|
|
||||||
image := CreateRandomImage() //nolint:staticcheck
|
image := CreateRandomImage()
|
||||||
manifestContent := image.ManifestDescriptor.Data
|
|
||||||
manifestDigest := image.ManifestDescriptor.Digest
|
|
||||||
|
|
||||||
localImgTrustStore, err := imagetrust.NewLocalImageTrustStore(rootDir)
|
localImgTrustStore, err := imagetrust.NewLocalImageTrustStore(rootDir)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
author, expTime, ok, err := localImgTrustStore.VerifySignature("cosign",
|
author, expTime, ok, err := localImgTrustStore.VerifySignature("cosign",
|
||||||
[]byte(""), "", manifestDigest, manifestContent, repo,
|
[]byte(""), "", image.Digest(), image.AsImageMeta(), repo,
|
||||||
)
|
)
|
||||||
So(author, ShouldBeEmpty)
|
So(author, ShouldBeEmpty)
|
||||||
So(expTime, ShouldBeZeroValue)
|
So(expTime, ShouldBeZeroValue)
|
||||||
@ -54,7 +52,7 @@ func TestImageTrust(t *testing.T) {
|
|||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
author, expTime, ok, err = cloudImgTrustStore.VerifySignature("cosign",
|
author, expTime, ok, err = cloudImgTrustStore.VerifySignature("cosign",
|
||||||
[]byte(""), "", manifestDigest, manifestContent, repo,
|
[]byte(""), "", image.Digest(), image.AsImageMeta(), repo,
|
||||||
)
|
)
|
||||||
So(author, ShouldBeEmpty)
|
So(author, ShouldBeEmpty)
|
||||||
So(expTime, ShouldBeZeroValue)
|
So(expTime, ShouldBeZeroValue)
|
||||||
|
@ -150,31 +150,21 @@ func TestInitCosignAndNotationDirs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestVerifySignatures(t *testing.T) {
|
func TestVerifySignatures(t *testing.T) {
|
||||||
Convey("wrong manifest content", t, func() {
|
|
||||||
manifestContent := []byte("wrong json")
|
|
||||||
|
|
||||||
imgTrustStore := &imagetrust.ImageTrustStore{}
|
|
||||||
_, _, _, err := imgTrustStore.VerifySignature("", []byte(""), "", "", manifestContent, "repo")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("empty manifest digest", t, func() {
|
Convey("empty manifest digest", t, func() {
|
||||||
image := CreateRandomImage()
|
image := CreateRandomImage()
|
||||||
manifestContent := image.ManifestDescriptor.Data
|
|
||||||
|
|
||||||
imgTrustStore := &imagetrust.ImageTrustStore{}
|
imgTrustStore := &imagetrust.ImageTrustStore{}
|
||||||
_, _, _, err := imgTrustStore.VerifySignature("", []byte(""), "", "", manifestContent, "repo")
|
_, _, _, err := imgTrustStore.VerifySignature("", []byte(""), "", "", image.AsImageMeta(), "repo")
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
So(err, ShouldEqual, zerr.ErrBadManifestDigest)
|
So(err, ShouldEqual, zerr.ErrBadManifestDigest)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("wrong signature type", t, func() {
|
Convey("wrong signature type", t, func() {
|
||||||
image := CreateRandomImage()
|
image := CreateRandomImage()
|
||||||
manifestContent := image.ManifestDescriptor.Data
|
|
||||||
manifestDigest := image.ManifestDescriptor.Digest
|
|
||||||
|
|
||||||
imgTrustStore := &imagetrust.ImageTrustStore{}
|
imgTrustStore := &imagetrust.ImageTrustStore{}
|
||||||
_, _, _, err := imgTrustStore.VerifySignature("wrongType", []byte(""), "", manifestDigest, manifestContent, "repo")
|
_, _, _, err := imgTrustStore.VerifySignature("wrongType", []byte(""), "", image.Digest(), image.AsImageMeta(),
|
||||||
|
"repo")
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
So(err, ShouldEqual, zerr.ErrInvalidSignatureType)
|
So(err, ShouldEqual, zerr.ErrInvalidSignatureType)
|
||||||
})
|
})
|
||||||
@ -184,15 +174,13 @@ func TestVerifySignatures(t *testing.T) {
|
|||||||
tag := "test" //nolint:goconst
|
tag := "test" //nolint:goconst
|
||||||
|
|
||||||
image := CreateRandomImage()
|
image := CreateRandomImage()
|
||||||
manifestContent := image.ManifestDescriptor.Data
|
|
||||||
manifestDigest := image.ManifestDescriptor.Digest
|
|
||||||
|
|
||||||
Convey("cosignDir is not set", func() {
|
Convey("cosignDir is not set", func() {
|
||||||
imgTrustStore := &imagetrust.ImageTrustStore{
|
imgTrustStore := &imagetrust.ImageTrustStore{
|
||||||
CosignStorage: &imagetrust.PublicKeyLocalStorage{},
|
CosignStorage: &imagetrust.PublicKeyLocalStorage{},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, _, err := imgTrustStore.VerifySignature("cosign", []byte(""), "", manifestDigest, manifestContent, repo)
|
_, _, _, err := imgTrustStore.VerifySignature("cosign", []byte(""), "", image.Digest(), image.AsImageMeta(), repo)
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
So(err, ShouldEqual, zerr.ErrSignConfigDirNotSet)
|
So(err, ShouldEqual, zerr.ErrSignConfigDirNotSet)
|
||||||
})
|
})
|
||||||
@ -212,7 +200,7 @@ func TestVerifySignatures(t *testing.T) {
|
|||||||
CosignStorage: pubKeyStorage,
|
CosignStorage: pubKeyStorage,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, _, err = imgTrustStore.VerifySignature("cosign", []byte(""), "", manifestDigest, manifestContent, repo)
|
_, _, _, err = imgTrustStore.VerifySignature("cosign", []byte(""), "", image.Digest(), image.AsImageMeta(), repo)
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -232,8 +220,8 @@ func TestVerifySignatures(t *testing.T) {
|
|||||||
CosignStorage: pubKeyStorage,
|
CosignStorage: pubKeyStorage,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, isTrusted, err := imgTrustStore.VerifySignature("cosign", []byte(""), "", manifestDigest,
|
_, _, isTrusted, err := imgTrustStore.VerifySignature("cosign", []byte(""), "", image.Digest(), image.AsImageMeta(),
|
||||||
manifestContent, repo)
|
repo)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(isTrusted, ShouldBeFalse)
|
So(isTrusted, ShouldBeFalse)
|
||||||
})
|
})
|
||||||
@ -282,7 +270,7 @@ func TestVerifySignatures(t *testing.T) {
|
|||||||
AnnotationOptions: options.AnnotationOptions{Annotations: []string{fmt.Sprintf("tag=%s", tag)}},
|
AnnotationOptions: options.AnnotationOptions{Annotations: []string{fmt.Sprintf("tag=%s", tag)}},
|
||||||
Upload: true,
|
Upload: true,
|
||||||
},
|
},
|
||||||
[]string{fmt.Sprintf("localhost:%s/%s@%s", port, repo, manifestDigest.String())})
|
[]string{fmt.Sprintf("localhost:%s/%s@%s", port, repo, image.DigestStr())})
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
err = os.Remove(path.Join(cosignDir, "cosign.key"))
|
err = os.Remove(path.Join(cosignDir, "cosign.key"))
|
||||||
@ -299,7 +287,7 @@ func TestVerifySignatures(t *testing.T) {
|
|||||||
var sigKey string
|
var sigKey string
|
||||||
|
|
||||||
for _, manifest := range index.Manifests {
|
for _, manifest := range index.Manifests {
|
||||||
if manifest.Digest != manifestDigest {
|
if manifest.Digest != image.Digest() {
|
||||||
blobContent, err := ctlr.StoreController.DefaultStore.GetBlobContent(repo, manifest.Digest)
|
blobContent, err := ctlr.StoreController.DefaultStore.GetBlobContent(repo, manifest.Digest)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
@ -320,8 +308,8 @@ func TestVerifySignatures(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// signature is trusted
|
// signature is trusted
|
||||||
author, _, isTrusted, err := imgTrustStore.VerifySignature("cosign", rawSignature, sigKey, manifestDigest,
|
author, _, isTrusted, err := imgTrustStore.VerifySignature("cosign", rawSignature, sigKey, image.Digest(),
|
||||||
manifestContent, repo)
|
image.AsImageMeta(), repo)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(isTrusted, ShouldBeTrue)
|
So(isTrusted, ShouldBeTrue)
|
||||||
So(author, ShouldNotBeEmpty)
|
So(author, ShouldNotBeEmpty)
|
||||||
@ -332,16 +320,14 @@ func TestVerifySignatures(t *testing.T) {
|
|||||||
repo := "repo" //nolint:goconst
|
repo := "repo" //nolint:goconst
|
||||||
tag := "test" //nolint:goconst
|
tag := "test" //nolint:goconst
|
||||||
image := CreateRandomImage()
|
image := CreateRandomImage()
|
||||||
manifestContent := image.ManifestDescriptor.Data
|
|
||||||
manifestDigest := image.ManifestDescriptor.Digest
|
|
||||||
|
|
||||||
Convey("notationDir is not set", func() {
|
Convey("notationDir is not set", func() {
|
||||||
imgTrustStore := &imagetrust.ImageTrustStore{
|
imgTrustStore := &imagetrust.ImageTrustStore{
|
||||||
NotationStorage: &imagetrust.CertificateLocalStorage{},
|
NotationStorage: &imagetrust.CertificateLocalStorage{},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, _, err := imgTrustStore.VerifySignature("notation", []byte("signature"), "", manifestDigest,
|
_, _, _, err := imgTrustStore.VerifySignature("notation", []byte("signature"), "", image.Digest(),
|
||||||
manifestContent, repo)
|
image.AsImageMeta(), repo)
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
So(err, ShouldEqual, zerr.ErrSignConfigDirNotSet)
|
So(err, ShouldEqual, zerr.ErrSignConfigDirNotSet)
|
||||||
})
|
})
|
||||||
@ -356,8 +342,8 @@ func TestVerifySignatures(t *testing.T) {
|
|||||||
NotationStorage: certStorage,
|
NotationStorage: certStorage,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, isTrusted, err := imgTrustStore.VerifySignature("notation", []byte(""), "", manifestDigest,
|
_, _, isTrusted, err := imgTrustStore.VerifySignature("notation", []byte(""), "", image.Digest(),
|
||||||
manifestContent, repo)
|
image.AsImageMeta(), repo)
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
So(isTrusted, ShouldBeFalse)
|
So(isTrusted, ShouldBeFalse)
|
||||||
})
|
})
|
||||||
@ -377,8 +363,8 @@ func TestVerifySignatures(t *testing.T) {
|
|||||||
NotationStorage: certStorage,
|
NotationStorage: certStorage,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, _, err = imgTrustStore.VerifySignature("notation", []byte("signature"), "", manifestDigest,
|
_, _, _, err = imgTrustStore.VerifySignature("notation", []byte("signature"), "", image.Digest(),
|
||||||
manifestContent, repo)
|
image.AsImageMeta(), repo)
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -399,8 +385,8 @@ func TestVerifySignatures(t *testing.T) {
|
|||||||
NotationStorage: certStorage,
|
NotationStorage: certStorage,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, _, err = imgTrustStore.VerifySignature("notation", []byte("signature"), "", manifestDigest, manifestContent,
|
_, _, _, err = imgTrustStore.VerifySignature("notation", []byte("signature"), "", image.Digest(),
|
||||||
repo)
|
image.AsImageMeta(), repo)
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -437,10 +423,10 @@ func TestVerifySignatures(t *testing.T) {
|
|||||||
err = signature.GenerateNotationCerts(notationDir, "notation-sign-test")
|
err = signature.GenerateNotationCerts(notationDir, "notation-sign-test")
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// sign the image
|
// sign the imageURL
|
||||||
image := fmt.Sprintf("localhost:%s/%s", port, fmt.Sprintf("%s:%s", repo, tag))
|
imageURL := fmt.Sprintf("localhost:%s/%s", port, fmt.Sprintf("%s:%s", repo, tag))
|
||||||
|
|
||||||
err = signature.SignWithNotation("notation-sign-test", image, notationDir, true)
|
err = signature.SignWithNotation("notation-sign-test", imageURL, notationDir, true)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
err = test.CopyFiles(path.Join(notationDir, "notation", "truststore"), path.Join(notationDir, "truststore"))
|
err = test.CopyFiles(path.Join(notationDir, "notation", "truststore"), path.Join(notationDir, "truststore"))
|
||||||
@ -481,7 +467,7 @@ func TestVerifySignatures(t *testing.T) {
|
|||||||
var sigKey string
|
var sigKey string
|
||||||
|
|
||||||
for _, manifest := range index.Manifests {
|
for _, manifest := range index.Manifests {
|
||||||
if manifest.Digest != manifestDigest {
|
if manifest.Digest != image.Digest() {
|
||||||
blobContent, err := ctlr.StoreController.DefaultStore.GetBlobContent(repo, manifest.Digest)
|
blobContent, err := ctlr.StoreController.DefaultStore.GetBlobContent(repo, manifest.Digest)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
@ -502,8 +488,8 @@ func TestVerifySignatures(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// signature is trusted
|
// signature is trusted
|
||||||
author, _, isTrusted, err := imgTrustStore.VerifySignature("notation", rawSignature, sigKey, manifestDigest,
|
author, _, isTrusted, err := imgTrustStore.VerifySignature("notation", rawSignature, sigKey, image.Digest(),
|
||||||
manifestContent, repo)
|
image.AsImageMeta(), repo)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(isTrusted, ShouldBeTrue)
|
So(isTrusted, ShouldBeTrue)
|
||||||
So(author, ShouldNotBeEmpty)
|
So(author, ShouldNotBeEmpty)
|
||||||
@ -512,8 +498,8 @@ func TestVerifySignatures(t *testing.T) {
|
|||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// signature is not trusted
|
// signature is not trusted
|
||||||
author, _, isTrusted, err = imgTrustStore.VerifySignature("notation", rawSignature, sigKey, manifestDigest,
|
author, _, isTrusted, err = imgTrustStore.VerifySignature("notation", rawSignature, sigKey, image.Digest(),
|
||||||
manifestContent, repo)
|
image.AsImageMeta(), repo)
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
So(isTrusted, ShouldBeFalse)
|
So(isTrusted, ShouldBeFalse)
|
||||||
So(author, ShouldNotBeEmpty)
|
So(author, ShouldNotBeEmpty)
|
||||||
@ -977,9 +963,6 @@ func TestAWSTrustStore(t *testing.T) {
|
|||||||
repo := "repo"
|
repo := "repo"
|
||||||
image := CreateRandomImage()
|
image := CreateRandomImage()
|
||||||
|
|
||||||
manifestContent := image.ManifestDescriptor.Data
|
|
||||||
manifestDigest := image.ManifestDescriptor.Digest
|
|
||||||
|
|
||||||
secretsManagerMock := mocks.SecretsManagerMock{
|
secretsManagerMock := mocks.SecretsManagerMock{
|
||||||
CreateSecretFn: func(ctx context.Context, params *secretsmanager.CreateSecretInput,
|
CreateSecretFn: func(ctx context.Context, params *secretsmanager.CreateSecretInput,
|
||||||
optFns ...func(*secretsmanager.Options),
|
optFns ...func(*secretsmanager.Options),
|
||||||
@ -1001,8 +984,8 @@ func TestAWSTrustStore(t *testing.T) {
|
|||||||
NotationStorage: notationStorage,
|
NotationStorage: notationStorage,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, _, err = imgTrustStore.VerifySignature("notation", []byte("signature"), "", manifestDigest,
|
_, _, _, err = imgTrustStore.VerifySignature("notation", []byte("signature"), "", image.Digest(),
|
||||||
manifestContent, repo)
|
image.AsImageMeta(), repo)
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1010,9 +993,6 @@ func TestAWSTrustStore(t *testing.T) {
|
|||||||
repo := "repo"
|
repo := "repo"
|
||||||
image := CreateRandomImage()
|
image := CreateRandomImage()
|
||||||
|
|
||||||
manifestContent := image.ManifestDescriptor.Data
|
|
||||||
manifestDigest := image.ManifestDescriptor.Digest
|
|
||||||
|
|
||||||
secretsManagerMock := mocks.SecretsManagerMock{
|
secretsManagerMock := mocks.SecretsManagerMock{
|
||||||
CreateSecretFn: func(ctx context.Context, params *secretsmanager.CreateSecretInput,
|
CreateSecretFn: func(ctx context.Context, params *secretsmanager.CreateSecretInput,
|
||||||
optFns ...func(*secretsmanager.Options),
|
optFns ...func(*secretsmanager.Options),
|
||||||
@ -1034,8 +1014,8 @@ func TestAWSTrustStore(t *testing.T) {
|
|||||||
NotationStorage: notationStorage,
|
NotationStorage: notationStorage,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, _, err = imgTrustStore.VerifySignature("notation", []byte("signature"), "", manifestDigest,
|
_, _, _, err = imgTrustStore.VerifySignature("notation", []byte("signature"), "", image.Digest(),
|
||||||
manifestContent, repo)
|
image.AsImageMeta(), repo)
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
|
|
||||||
secretsManagerCacheMock = mocks.SecretsManagerCacheMock{
|
secretsManagerCacheMock = mocks.SecretsManagerCacheMock{
|
||||||
@ -1051,8 +1031,8 @@ func TestAWSTrustStore(t *testing.T) {
|
|||||||
NotationStorage: notationStorage,
|
NotationStorage: notationStorage,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, _, err = imgTrustStore.VerifySignature("notation", []byte("signature"), "", manifestDigest,
|
_, _, _, err = imgTrustStore.VerifySignature("notation", []byte("signature"), "", image.Digest(),
|
||||||
manifestContent, repo)
|
image.AsImageMeta(), repo)
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
|
|
||||||
secretsManagerCacheMock = mocks.SecretsManagerCacheMock{
|
secretsManagerCacheMock = mocks.SecretsManagerCacheMock{
|
||||||
@ -1068,8 +1048,8 @@ func TestAWSTrustStore(t *testing.T) {
|
|||||||
NotationStorage: notationStorage,
|
NotationStorage: notationStorage,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, _, err = imgTrustStore.VerifySignature("notation", []byte("signature"), "", manifestDigest,
|
_, _, _, err = imgTrustStore.VerifySignature("notation", []byte("signature"), "", image.Digest(),
|
||||||
manifestContent, repo)
|
image.AsImageMeta(), repo)
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1080,19 +1060,19 @@ func TestAWSTrustStore(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repoMetaTablename := "RepoMetadataTable" + uuid.String()
|
repoMetaTablename := "RepoMetadataTable" + uuid.String()
|
||||||
manifestDataTablename := "ManifestDataTable" + uuid.String()
|
|
||||||
versionTablename := "Version" + uuid.String()
|
versionTablename := "Version" + uuid.String()
|
||||||
indexDataTablename := "IndexDataTable" + uuid.String()
|
|
||||||
userDataTablename := "UserDataTable" + uuid.String()
|
userDataTablename := "UserDataTable" + uuid.String()
|
||||||
apiKeyTablename := "ApiKeyTable" + uuid.String()
|
apiKeyTablename := "ApiKeyTable" + uuid.String()
|
||||||
|
imageMetaTablename := "imageMetaTable" + uuid.String()
|
||||||
|
repoBlobsInfoTablename := "repoBlobsInfoTable" + uuid.String()
|
||||||
|
|
||||||
dynamoDBDriverParams := map[string]interface{}{
|
dynamoDBDriverParams := map[string]interface{}{
|
||||||
"name": "dynamoDB",
|
"name": "dynamoDB",
|
||||||
"endpoint": os.Getenv("DYNAMODBMOCK_ENDPOINT"),
|
"endpoint": os.Getenv("DYNAMODBMOCK_ENDPOINT"),
|
||||||
"region": "us-east-2",
|
"region": "us-east-2",
|
||||||
"repometatablename": repoMetaTablename,
|
"repometatablename": repoMetaTablename,
|
||||||
"manifestdatatablename": manifestDataTablename,
|
"imagemetatablename": imageMetaTablename,
|
||||||
"indexdatatablename": indexDataTablename,
|
"repoblobsinfotablename": repoBlobsInfoTablename,
|
||||||
"userdatatablename": userDataTablename,
|
"userdatatablename": userDataTablename,
|
||||||
"apikeytablename": apiKeyTablename,
|
"apikeytablename": apiKeyTablename,
|
||||||
"versiontablename": versionTablename,
|
"versiontablename": versionTablename,
|
||||||
@ -1237,8 +1217,6 @@ func RunVerificationTests(t *testing.T, dbDriverParams map[string]interface{}) {
|
|||||||
|
|
||||||
Convey("verify cosign signature is trusted", func() {
|
Convey("verify cosign signature is trusted", func() {
|
||||||
image := CreateRandomImage()
|
image := CreateRandomImage()
|
||||||
manifestContent := image.ManifestDescriptor.Data
|
|
||||||
manifestDigest := image.ManifestDescriptor.Digest
|
|
||||||
|
|
||||||
err = UploadImage(image, baseURL, repo, tag)
|
err = UploadImage(image, baseURL, repo, tag)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
@ -1264,7 +1242,7 @@ func RunVerificationTests(t *testing.T, dbDriverParams map[string]interface{}) {
|
|||||||
AnnotationOptions: options.AnnotationOptions{Annotations: []string{fmt.Sprintf("tag=%s", tag)}},
|
AnnotationOptions: options.AnnotationOptions{Annotations: []string{fmt.Sprintf("tag=%s", tag)}},
|
||||||
Upload: true,
|
Upload: true,
|
||||||
},
|
},
|
||||||
[]string{fmt.Sprintf("localhost:%s/%s@%s", port, repo, manifestDigest.String())})
|
[]string{fmt.Sprintf("localhost:%s/%s@%s", port, repo, image.DigestStr())})
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
indexContent, err := ctlr.StoreController.DefaultStore.GetIndexContent(repo)
|
indexContent, err := ctlr.StoreController.DefaultStore.GetIndexContent(repo)
|
||||||
@ -1278,7 +1256,7 @@ func RunVerificationTests(t *testing.T, dbDriverParams map[string]interface{}) {
|
|||||||
var sigKey string
|
var sigKey string
|
||||||
|
|
||||||
for _, manifest := range index.Manifests {
|
for _, manifest := range index.Manifests {
|
||||||
if manifest.Digest != manifestDigest {
|
if manifest.Digest != image.Digest() {
|
||||||
blobContent, err := ctlr.StoreController.DefaultStore.GetBlobContent(repo, manifest.Digest)
|
blobContent, err := ctlr.StoreController.DefaultStore.GetBlobContent(repo, manifest.Digest)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
@ -1308,8 +1286,8 @@ func RunVerificationTests(t *testing.T, dbDriverParams map[string]interface{}) {
|
|||||||
imageTrustStore := ctlr.MetaDB.ImageTrustStore()
|
imageTrustStore := ctlr.MetaDB.ImageTrustStore()
|
||||||
|
|
||||||
// signature is trusted
|
// signature is trusted
|
||||||
author, _, isTrusted, err := imageTrustStore.VerifySignature("cosign", rawSignature, sigKey, manifestDigest,
|
author, _, isTrusted, err := imageTrustStore.VerifySignature("cosign", rawSignature, sigKey, image.Digest(),
|
||||||
manifestContent, repo)
|
image.AsImageMeta(), repo)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(isTrusted, ShouldBeTrue)
|
So(isTrusted, ShouldBeTrue)
|
||||||
So(author, ShouldNotBeEmpty)
|
So(author, ShouldNotBeEmpty)
|
||||||
@ -1317,8 +1295,6 @@ func RunVerificationTests(t *testing.T, dbDriverParams map[string]interface{}) {
|
|||||||
|
|
||||||
Convey("verify notation signature is trusted", func() {
|
Convey("verify notation signature is trusted", func() {
|
||||||
image := CreateRandomImage()
|
image := CreateRandomImage()
|
||||||
manifestContent := image.ManifestDescriptor.Data
|
|
||||||
manifestDigest := image.ManifestDescriptor.Digest
|
|
||||||
|
|
||||||
err = UploadImage(image, baseURL, repo, tag)
|
err = UploadImage(image, baseURL, repo, tag)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
@ -1366,7 +1342,7 @@ func RunVerificationTests(t *testing.T, dbDriverParams map[string]interface{}) {
|
|||||||
|
|
||||||
t.Logf("Processing manifest %v", notationSig)
|
t.Logf("Processing manifest %v", notationSig)
|
||||||
if notationSig.Config.MediaType != notreg.ArtifactTypeNotation ||
|
if notationSig.Config.MediaType != notreg.ArtifactTypeNotation ||
|
||||||
notationSig.Subject.Digest != manifestDigest {
|
notationSig.Subject.Digest != image.Digest() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1400,8 +1376,8 @@ func RunVerificationTests(t *testing.T, dbDriverParams map[string]interface{}) {
|
|||||||
imageTrustStore := ctlr.MetaDB.ImageTrustStore()
|
imageTrustStore := ctlr.MetaDB.ImageTrustStore()
|
||||||
|
|
||||||
// signature is trusted
|
// signature is trusted
|
||||||
author, _, isTrusted, err := imageTrustStore.VerifySignature("notation", rawSignature, sigKey, manifestDigest,
|
author, _, isTrusted, err := imageTrustStore.VerifySignature("notation", rawSignature, sigKey, image.Digest(),
|
||||||
manifestContent, repo)
|
image.AsImageMeta(), repo)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(isTrusted, ShouldBeTrue)
|
So(isTrusted, ShouldBeTrue)
|
||||||
So(author, ShouldEqual, "CN=cert,O=Notary,L=Seattle,ST=WA,C=US")
|
So(author, ShouldEqual, "CN=cert,O=Notary,L=Seattle,ST=WA,C=US")
|
||||||
|
@ -4,12 +4,10 @@ package convert
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/99designs/gqlgen/graphql"
|
"github.com/99designs/gqlgen/graphql"
|
||||||
godigest "github.com/opencontainers/go-digest"
|
|
||||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
|
||||||
@ -17,7 +15,7 @@ import (
|
|||||||
"zotregistry.io/zot/pkg/extensions/search/gql_generated"
|
"zotregistry.io/zot/pkg/extensions/search/gql_generated"
|
||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
"zotregistry.io/zot/pkg/meta/boltdb"
|
"zotregistry.io/zot/pkg/meta/boltdb"
|
||||||
mTypes "zotregistry.io/zot/pkg/meta/types"
|
. "zotregistry.io/zot/pkg/test/image-utils"
|
||||||
"zotregistry.io/zot/pkg/test/mocks"
|
"zotregistry.io/zot/pkg/test/mocks"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -34,33 +32,20 @@ func TestCVEConvert(t *testing.T) {
|
|||||||
metaDB, err := boltdb.New(boltDB, log.NewLogger("debug", ""))
|
metaDB, err := boltdb.New(boltDB, log.NewLogger("debug", ""))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
configBlob, err := json.Marshal(ispec.Image{})
|
image := CreateImageWith().
|
||||||
So(err, ShouldBeNil)
|
Layers([]Layer{{
|
||||||
|
|
||||||
manifestBlob, err := json.Marshal(ispec.Manifest{
|
|
||||||
Layers: []ispec.Descriptor{
|
|
||||||
{
|
|
||||||
MediaType: ispec.MediaTypeImageLayerGzip,
|
MediaType: ispec.MediaTypeImageLayerGzip,
|
||||||
Size: 0,
|
Digest: ispec.MediaTypeEmptyJSON,
|
||||||
Digest: godigest.NewDigestFromEncoded(godigest.SHA256, "digest"),
|
Blob: ispec.DescriptorEmptyJSON.Data,
|
||||||
},
|
}}).DefaultConfig().Build()
|
||||||
},
|
|
||||||
})
|
err = metaDB.SetRepoReference("repo1", "0.1.0", image.AsImageMeta())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
repoMeta11 := mTypes.ManifestMetadata{
|
repoMetaList, err := metaDB.SearchRepos(context.Background(), "")
|
||||||
ManifestBlob: manifestBlob,
|
|
||||||
ConfigBlob: configBlob,
|
|
||||||
}
|
|
||||||
|
|
||||||
digest11 := godigest.FromString("abc1")
|
|
||||||
err = metaDB.SetManifestMeta("repo1", digest11, repoMeta11)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference("repo1", "0.1.0", digest11, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
reposMeta, manifestMetaMap, _, err := metaDB.SearchRepos(context.Background(), "")
|
imageMeta, err := metaDB.FilterImageMeta(context.Background(), []string{image.DigestStr()})
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
ctx := graphql.WithResponseContext(context.Background(),
|
ctx := graphql.WithResponseContext(context.Background(),
|
||||||
graphql.DefaultErrorPresenter, graphql.DefaultRecover)
|
graphql.DefaultErrorPresenter, graphql.DefaultRecover)
|
||||||
@ -86,8 +71,8 @@ func TestCVEConvert(t *testing.T) {
|
|||||||
So(imageSummary, ShouldBeNil)
|
So(imageSummary, ShouldBeNil)
|
||||||
So(graphql.GetErrors(ctx), ShouldBeNil)
|
So(graphql.GetErrors(ctx), ShouldBeNil)
|
||||||
|
|
||||||
imageSummary, _, err = ImageManifest2ImageSummary(ctx, "repo1", "0.1.0", digest11, reposMeta[0],
|
imageSummary, _, err = ImageManifest2ImageSummary(ctx, GetFullImageMeta("0.1.0", repoMetaList[0],
|
||||||
manifestMetaMap[digest11.String()])
|
imageMeta[image.DigestStr()]))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
So(imageSummary, ShouldNotBeNil)
|
So(imageSummary, ShouldNotBeNil)
|
||||||
@ -177,8 +162,8 @@ func TestCVEConvert(t *testing.T) {
|
|||||||
So(repoSummary, ShouldBeNil)
|
So(repoSummary, ShouldBeNil)
|
||||||
So(graphql.GetErrors(ctx), ShouldBeNil)
|
So(graphql.GetErrors(ctx), ShouldBeNil)
|
||||||
|
|
||||||
imageSummary, _, err := ImageManifest2ImageSummary(ctx, "repo1", "0.1.0", digest11, reposMeta[0],
|
imageSummary, _, err := ImageManifest2ImageSummary(ctx, GetFullImageMeta("0.1.0", repoMetaList[0],
|
||||||
manifestMetaMap[digest11.String()])
|
imageMeta[image.DigestStr()]))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
So(imageSummary, ShouldNotBeNil)
|
So(imageSummary, ShouldNotBeNil)
|
||||||
@ -235,8 +220,8 @@ func TestCVEConvert(t *testing.T) {
|
|||||||
So(manifestSummary, ShouldBeNil)
|
So(manifestSummary, ShouldBeNil)
|
||||||
So(graphql.GetErrors(ctx), ShouldBeNil)
|
So(graphql.GetErrors(ctx), ShouldBeNil)
|
||||||
|
|
||||||
imageSummary, _, err := ImageManifest2ImageSummary(ctx, "repo1", "0.1.0", digest11, reposMeta[0],
|
imageSummary, _, err := ImageManifest2ImageSummary(ctx, GetFullImageMeta("0.1.0", repoMetaList[0],
|
||||||
manifestMetaMap[digest11.String()])
|
imageMeta[image.DigestStr()]))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
manifestSummary = imageSummary.Manifests[0]
|
manifestSummary = imageSummary.Manifests[0]
|
||||||
|
|
||||||
|
@ -4,21 +4,19 @@ package convert_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/99designs/gqlgen/graphql"
|
|
||||||
godigest "github.com/opencontainers/go-digest"
|
godigest "github.com/opencontainers/go-digest"
|
||||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
|
||||||
"zotregistry.io/zot/pkg/extensions/search/convert"
|
"zotregistry.io/zot/pkg/extensions/search/convert"
|
||||||
cvemodel "zotregistry.io/zot/pkg/extensions/search/cve/model"
|
|
||||||
"zotregistry.io/zot/pkg/extensions/search/gql_generated"
|
"zotregistry.io/zot/pkg/extensions/search/gql_generated"
|
||||||
"zotregistry.io/zot/pkg/extensions/search/pagination"
|
"zotregistry.io/zot/pkg/extensions/search/pagination"
|
||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
|
"zotregistry.io/zot/pkg/meta/boltdb"
|
||||||
mTypes "zotregistry.io/zot/pkg/meta/types"
|
mTypes "zotregistry.io/zot/pkg/meta/types"
|
||||||
. "zotregistry.io/zot/pkg/test/image-utils"
|
. "zotregistry.io/zot/pkg/test/image-utils"
|
||||||
"zotregistry.io/zot/pkg/test/mocks"
|
"zotregistry.io/zot/pkg/test/mocks"
|
||||||
@ -27,187 +25,6 @@ import (
|
|||||||
|
|
||||||
var ErrTestError = errors.New("TestError")
|
var ErrTestError = errors.New("TestError")
|
||||||
|
|
||||||
func TestConvertErrors(t *testing.T) {
|
|
||||||
Convey("ImageIndex2ImageSummary errors", t, func() {
|
|
||||||
ctx := graphql.WithResponseContext(context.Background(),
|
|
||||||
graphql.DefaultErrorPresenter, graphql.DefaultRecover)
|
|
||||||
|
|
||||||
_, _, err := convert.ImageIndex2ImageSummary(
|
|
||||||
ctx,
|
|
||||||
"repo",
|
|
||||||
"tag",
|
|
||||||
godigest.FromString("indexDigest"),
|
|
||||||
mTypes.RepoMetadata{},
|
|
||||||
mTypes.IndexData{
|
|
||||||
IndexBlob: []byte("bad json"),
|
|
||||||
},
|
|
||||||
map[string]mTypes.ManifestMetadata{},
|
|
||||||
)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("ImageIndex2ImageSummary cve scanning", t, func() {
|
|
||||||
ctx := graphql.WithResponseContext(context.Background(),
|
|
||||||
graphql.DefaultErrorPresenter, graphql.DefaultRecover)
|
|
||||||
|
|
||||||
_, _, err := convert.ImageIndex2ImageSummary(
|
|
||||||
ctx,
|
|
||||||
"repo",
|
|
||||||
"tag",
|
|
||||||
godigest.FromString("indexDigest"),
|
|
||||||
mTypes.RepoMetadata{},
|
|
||||||
mTypes.IndexData{
|
|
||||||
IndexBlob: []byte("{}"),
|
|
||||||
},
|
|
||||||
map[string]mTypes.ManifestMetadata{},
|
|
||||||
)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("ImageManifest2ImageSummary", t, func() {
|
|
||||||
ctx := graphql.WithResponseContext(context.Background(),
|
|
||||||
graphql.DefaultErrorPresenter, graphql.DefaultRecover)
|
|
||||||
configBlob, err := json.Marshal(ispec.Image{
|
|
||||||
Platform: ispec.Platform{
|
|
||||||
OS: "os",
|
|
||||||
Architecture: "arch",
|
|
||||||
Variant: "var",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, err = convert.ImageManifest2ImageSummary(
|
|
||||||
ctx,
|
|
||||||
"repo",
|
|
||||||
"tag",
|
|
||||||
godigest.FromString("manifestDigest"),
|
|
||||||
mTypes.RepoMetadata{},
|
|
||||||
mTypes.ManifestMetadata{
|
|
||||||
ManifestBlob: []byte("{}"),
|
|
||||||
ConfigBlob: configBlob,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("ImageManifest2ManifestSummary", t, func() {
|
|
||||||
ctx := graphql.WithResponseContext(context.Background(),
|
|
||||||
graphql.DefaultErrorPresenter, graphql.DefaultRecover)
|
|
||||||
|
|
||||||
// with bad config json, shouldn't error when unmarshaling
|
|
||||||
_, _, _, err := convert.ImageManifest2ManifestSummary(
|
|
||||||
ctx,
|
|
||||||
"repo",
|
|
||||||
"tag",
|
|
||||||
ispec.Descriptor{
|
|
||||||
Digest: "dig",
|
|
||||||
MediaType: ispec.MediaTypeImageManifest,
|
|
||||||
},
|
|
||||||
mTypes.RepoMetadata{
|
|
||||||
Tags: map[string]mTypes.Descriptor{},
|
|
||||||
Statistics: map[string]mTypes.DescriptorStatistics{},
|
|
||||||
Signatures: map[string]mTypes.ManifestSignatures{},
|
|
||||||
Referrers: map[string][]mTypes.ReferrerInfo{},
|
|
||||||
},
|
|
||||||
mTypes.ManifestMetadata{
|
|
||||||
ManifestBlob: []byte(`{}`),
|
|
||||||
ConfigBlob: []byte("bad json"),
|
|
||||||
},
|
|
||||||
nil,
|
|
||||||
)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
// CVE scan using platform
|
|
||||||
configBlob, err := json.Marshal(ispec.Image{
|
|
||||||
Platform: ispec.Platform{
|
|
||||||
OS: "os",
|
|
||||||
Architecture: "arch",
|
|
||||||
Variant: "var",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = convert.ImageManifest2ManifestSummary(
|
|
||||||
ctx,
|
|
||||||
"repo",
|
|
||||||
"tag",
|
|
||||||
ispec.Descriptor{
|
|
||||||
Digest: "dig",
|
|
||||||
MediaType: ispec.MediaTypeImageManifest,
|
|
||||||
},
|
|
||||||
mTypes.RepoMetadata{
|
|
||||||
Tags: map[string]mTypes.Descriptor{},
|
|
||||||
Statistics: map[string]mTypes.DescriptorStatistics{},
|
|
||||||
Signatures: map[string]mTypes.ManifestSignatures{"dig": {"cosine": []mTypes.SignatureInfo{{}}}},
|
|
||||||
Referrers: map[string][]mTypes.ReferrerInfo{},
|
|
||||||
},
|
|
||||||
mTypes.ManifestMetadata{
|
|
||||||
ManifestBlob: []byte("{}"),
|
|
||||||
ConfigBlob: configBlob,
|
|
||||||
},
|
|
||||||
nil,
|
|
||||||
)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("RepoMeta2ExpandedRepoInfo", t, func() {
|
|
||||||
ctx := graphql.WithResponseContext(context.Background(),
|
|
||||||
graphql.DefaultErrorPresenter, graphql.DefaultRecover)
|
|
||||||
|
|
||||||
// with bad config json, error while unmarshaling
|
|
||||||
_, imageSummaries := convert.RepoMeta2ExpandedRepoInfo(
|
|
||||||
ctx,
|
|
||||||
mTypes.RepoMetadata{
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"tag1": {Digest: "dig", MediaType: ispec.MediaTypeImageManifest},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
map[string]mTypes.ManifestMetadata{
|
|
||||||
"dig": {
|
|
||||||
ManifestBlob: []byte("{}"),
|
|
||||||
ConfigBlob: []byte("bad json"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
map[string]mTypes.IndexData{},
|
|
||||||
convert.SkipQGLField{
|
|
||||||
Vulnerabilities: false,
|
|
||||||
},
|
|
||||||
mocks.CveInfoMock{
|
|
||||||
GetCVESummaryForImageMediaFn: func(repo, digest, mediaType string) (cvemodel.ImageCVESummary, error) {
|
|
||||||
return cvemodel.ImageCVESummary{}, ErrTestError
|
|
||||||
},
|
|
||||||
}, log.NewLogger("debug", ""),
|
|
||||||
)
|
|
||||||
So(len(imageSummaries), ShouldEqual, 1)
|
|
||||||
|
|
||||||
// cveInfo present no error
|
|
||||||
_, imageSummaries = convert.RepoMeta2ExpandedRepoInfo(
|
|
||||||
ctx,
|
|
||||||
mTypes.RepoMetadata{
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"tag1": {Digest: "dig", MediaType: ispec.MediaTypeImageManifest},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
map[string]mTypes.ManifestMetadata{
|
|
||||||
"dig": {
|
|
||||||
ManifestBlob: []byte("{}"),
|
|
||||||
ConfigBlob: []byte("{}"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
map[string]mTypes.IndexData{},
|
|
||||||
convert.SkipQGLField{
|
|
||||||
Vulnerabilities: false,
|
|
||||||
},
|
|
||||||
mocks.CveInfoMock{
|
|
||||||
GetCVESummaryForImageMediaFn: func(repo, digest, mediaType string) (cvemodel.ImageCVESummary, error) {
|
|
||||||
return cvemodel.ImageCVESummary{}, ErrTestError
|
|
||||||
},
|
|
||||||
}, log.NewLogger("debug", ""),
|
|
||||||
)
|
|
||||||
So(len(imageSummaries), ShouldEqual, 1)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUpdateLastUpdatedTimestamp(t *testing.T) {
|
func TestUpdateLastUpdatedTimestamp(t *testing.T) {
|
||||||
Convey("Image summary is the first image checked for the repo", t, func() {
|
Convey("Image summary is the first image checked for the repo", t, func() {
|
||||||
before := time.Time{}
|
before := time.Time{}
|
||||||
@ -300,14 +117,25 @@ func TestLabels(t *testing.T) {
|
|||||||
|
|
||||||
func TestGetSignaturesInfo(t *testing.T) {
|
func TestGetSignaturesInfo(t *testing.T) {
|
||||||
Convey("Test get signatures info - cosign", t, func() {
|
Convey("Test get signatures info - cosign", t, func() {
|
||||||
indexDigest := godigest.FromString("123")
|
digest := godigest.FromString("dig")
|
||||||
repoMeta := mTypes.RepoMetadata{
|
signatures := map[string]mTypes.ManifestSignatures{
|
||||||
Signatures: map[string]mTypes.ManifestSignatures{string(indexDigest): {"cosign": []mTypes.SignatureInfo{{
|
digest.String(): {
|
||||||
LayersInfo: []mTypes.LayerInfo{{LayerContent: []byte{}, LayerDigest: "", SignatureKey: "", Signer: "author"}},
|
"cosign": []mTypes.SignatureInfo{
|
||||||
}}}},
|
{
|
||||||
|
LayersInfo: []mTypes.LayerInfo{
|
||||||
|
{
|
||||||
|
LayerContent: []byte{},
|
||||||
|
LayerDigest: "",
|
||||||
|
SignatureKey: "",
|
||||||
|
Signer: "author",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
signaturesSummary := convert.GetSignaturesInfo(true, repoMeta, indexDigest)
|
signaturesSummary := convert.GetSignaturesInfo(true, signatures[digest.String()])
|
||||||
So(signaturesSummary, ShouldNotBeEmpty)
|
So(signaturesSummary, ShouldNotBeEmpty)
|
||||||
So(*signaturesSummary[0].Author, ShouldEqual, "author")
|
So(*signaturesSummary[0].Author, ShouldEqual, "author")
|
||||||
So(*signaturesSummary[0].IsTrusted, ShouldEqual, true)
|
So(*signaturesSummary[0].IsTrusted, ShouldEqual, true)
|
||||||
@ -315,9 +143,11 @@ func TestGetSignaturesInfo(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
Convey("Test get signatures info - notation", t, func() {
|
Convey("Test get signatures info - notation", t, func() {
|
||||||
indexDigest := godigest.FromString("123")
|
digest := godigest.FromString("dig")
|
||||||
repoMeta := mTypes.RepoMetadata{
|
signatures := map[string]mTypes.ManifestSignatures{
|
||||||
Signatures: map[string]mTypes.ManifestSignatures{string(indexDigest): {"notation": []mTypes.SignatureInfo{{
|
digest.String(): {
|
||||||
|
"notation": []mTypes.SignatureInfo{
|
||||||
|
{
|
||||||
LayersInfo: []mTypes.LayerInfo{
|
LayersInfo: []mTypes.LayerInfo{
|
||||||
{
|
{
|
||||||
LayerContent: []byte{},
|
LayerContent: []byte{},
|
||||||
@ -327,10 +157,12 @@ func TestGetSignaturesInfo(t *testing.T) {
|
|||||||
Date: time.Now().AddDate(0, 0, -1),
|
Date: time.Now().AddDate(0, 0, -1),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}}}},
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
signaturesSummary := convert.GetSignaturesInfo(true, repoMeta, indexDigest)
|
signaturesSummary := convert.GetSignaturesInfo(true, signatures[digest.String()])
|
||||||
So(signaturesSummary, ShouldNotBeEmpty)
|
So(signaturesSummary, ShouldNotBeEmpty)
|
||||||
So(*signaturesSummary[0].Author, ShouldEqual, "author")
|
So(*signaturesSummary[0].Author, ShouldEqual, "author")
|
||||||
So(*signaturesSummary[0].IsTrusted, ShouldEqual, false)
|
So(*signaturesSummary[0].IsTrusted, ShouldEqual, false)
|
||||||
@ -422,6 +254,18 @@ func ref[T any](val T) *T {
|
|||||||
func TestPaginatedConvert(t *testing.T) {
|
func TestPaginatedConvert(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
|
||||||
|
driver, err := boltdb.GetBoltDriver(boltdb.DBParameters{RootDir: tempDir})
|
||||||
|
if err != nil {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
metaDB, err := boltdb.New(driver, log.NewLogger("debug", ""))
|
||||||
|
if err != nil {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
badBothImage = CreateImageWith().DefaultLayers().ImageConfig(
|
badBothImage = CreateImageWith().DefaultLayers().ImageConfig(
|
||||||
ispec.Image{Platform: ispec.Platform{OS: "bad-os", Architecture: "bad-arch"}}).Build()
|
ispec.Image{Platform: ispec.Platform{OS: "bad-os", Architecture: "bad-arch"}}).Build()
|
||||||
@ -434,6 +278,7 @@ func TestPaginatedConvert(t *testing.T) {
|
|||||||
|
|
||||||
randomImage1 = CreateRandomImage()
|
randomImage1 = CreateRandomImage()
|
||||||
randomImage2 = CreateRandomImage()
|
randomImage2 = CreateRandomImage()
|
||||||
|
signatureDigest = godigest.FromString("signature")
|
||||||
|
|
||||||
badMultiArch = CreateMultiarchWith().Images(
|
badMultiArch = CreateMultiarchWith().Images(
|
||||||
[]Image{badBothImage, badOsImage, badArchImage, randomImage1}).Build()
|
[]Image{badBothImage, badOsImage, badArchImage, randomImage1}).Build()
|
||||||
@ -441,14 +286,14 @@ func TestPaginatedConvert(t *testing.T) {
|
|||||||
[]Image{badOsImage, badArchImage, randomImage2, goodImage}).Build()
|
[]Image{badOsImage, badArchImage, randomImage2, goodImage}).Build()
|
||||||
)
|
)
|
||||||
|
|
||||||
reposMeta, manifestMetaMap, indexDataMap := ociutils.GetMetadataForRepos(
|
ctx, err = ociutils.InitializeTestMetaDB(ctx, metaDB,
|
||||||
ociutils.Repo{
|
ociutils.Repo{
|
||||||
Name: "repo1-only-images",
|
Name: "repo1-only-images",
|
||||||
Images: []ociutils.RepoImage{
|
Images: []ociutils.RepoImage{
|
||||||
{Image: goodImage, Tag: "goodImage"},
|
{Image: goodImage, Reference: "goodImage"},
|
||||||
{Image: badOsImage, Tag: "badOsImage"},
|
{Image: badOsImage, Reference: "badOsImage"},
|
||||||
{Image: badArchImage, Tag: "badArchImage"},
|
{Image: badArchImage, Reference: "badArchImage"},
|
||||||
{Image: badBothImage, Tag: "badBothImage"},
|
{Image: badBothImage, Reference: "badBothImage"},
|
||||||
},
|
},
|
||||||
IsBookmarked: true,
|
IsBookmarked: true,
|
||||||
IsStarred: true,
|
IsStarred: true,
|
||||||
@ -456,9 +301,9 @@ func TestPaginatedConvert(t *testing.T) {
|
|||||||
ociutils.Repo{
|
ociutils.Repo{
|
||||||
Name: "repo2-only-bad-images",
|
Name: "repo2-only-bad-images",
|
||||||
Images: []ociutils.RepoImage{
|
Images: []ociutils.RepoImage{
|
||||||
{Image: randomImage1, Tag: "randomImage1"},
|
{Image: randomImage1, Reference: "randomImage1"},
|
||||||
{Image: randomImage2, Tag: "randomImage2"},
|
{Image: randomImage2, Reference: "randomImage2"},
|
||||||
{Image: badBothImage, Tag: "badBothImage"},
|
{Image: badBothImage, Reference: "badBothImage"},
|
||||||
},
|
},
|
||||||
IsBookmarked: true,
|
IsBookmarked: true,
|
||||||
IsStarred: true,
|
IsStarred: true,
|
||||||
@ -466,8 +311,8 @@ func TestPaginatedConvert(t *testing.T) {
|
|||||||
ociutils.Repo{
|
ociutils.Repo{
|
||||||
Name: "repo3-only-multiarch",
|
Name: "repo3-only-multiarch",
|
||||||
MultiArchImages: []ociutils.RepoMultiArchImage{
|
MultiArchImages: []ociutils.RepoMultiArchImage{
|
||||||
{MultiarchImage: badMultiArch, Tag: "badMultiArch"},
|
{MultiarchImage: badMultiArch, Reference: "badMultiArch"},
|
||||||
{MultiarchImage: goodMultiArch, Tag: "goodMultiArch"},
|
{MultiarchImage: goodMultiArch, Reference: "goodMultiArch"},
|
||||||
},
|
},
|
||||||
IsBookmarked: true,
|
IsBookmarked: true,
|
||||||
IsStarred: true,
|
IsStarred: true,
|
||||||
@ -475,44 +320,56 @@ func TestPaginatedConvert(t *testing.T) {
|
|||||||
ociutils.Repo{
|
ociutils.Repo{
|
||||||
Name: "repo4-not-bookmarked-or-starred",
|
Name: "repo4-not-bookmarked-or-starred",
|
||||||
Images: []ociutils.RepoImage{
|
Images: []ociutils.RepoImage{
|
||||||
{Image: goodImage, Tag: "goodImage"},
|
{Image: goodImage, Reference: "goodImage"},
|
||||||
},
|
},
|
||||||
MultiArchImages: []ociutils.RepoMultiArchImage{
|
MultiArchImages: []ociutils.RepoMultiArchImage{
|
||||||
{MultiarchImage: goodMultiArch, Tag: "goodMultiArch"},
|
{MultiarchImage: goodMultiArch, Reference: "goodMultiArch"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ociutils.Repo{
|
ociutils.Repo{
|
||||||
Name: "repo5-signed",
|
Name: "repo5-signed",
|
||||||
Images: []ociutils.RepoImage{
|
Images: []ociutils.RepoImage{
|
||||||
{Image: goodImage, Tag: "goodImage"}, // is fake signed by the image below
|
{Image: goodImage, Reference: "goodImage"}, // is fake signed by the image below
|
||||||
{Image: CreateFakeTestSignature(goodImage.DescriptorRef())},
|
},
|
||||||
|
Signatures: map[string]mTypes.ManifestSignatures{
|
||||||
|
goodImage.DigestStr(): ociutils.GetFakeSignatureInfo(signatureDigest.String()),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
skipCVE := convert.SkipQGLField{Vulnerabilities: true}
|
skipCVE := convert.SkipQGLField{Vulnerabilities: true}
|
||||||
|
|
||||||
Convey("PaginatedRepoMeta2RepoSummaries filtering and sorting", t, func() {
|
Convey("PaginatedRepoMeta2RepoSummaries filtering and sorting", t, func() {
|
||||||
// Test different combinations of the filter
|
// Test different combinations of the filter
|
||||||
|
repoMetaList, err := metaDB.FilterRepos(ctx, mTypes.AcceptAllRepoNames, mTypes.AcceptAllRepoMeta)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
imageMeta, err := metaDB.FilterImageMeta(ctx, mTypes.GetLatestImageDigests(repoMetaList))
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
reposSum, pageInfo, err := convert.PaginatedRepoMeta2RepoSummaries(
|
reposSum, pageInfo, err := convert.PaginatedRepoMeta2RepoSummaries(
|
||||||
ctx, reposMeta, manifestMetaMap, indexDataMap, skipCVE, mocks.CveInfoMock{},
|
ctx, repoMetaList, imageMeta,
|
||||||
mTypes.Filter{
|
mTypes.Filter{
|
||||||
Os: []*string{ref("good-os")},
|
Os: []*string{ref("good-os")},
|
||||||
Arch: []*string{ref("good-arch")},
|
Arch: []*string{ref("good-arch")},
|
||||||
IsBookmarked: ref(true),
|
IsBookmarked: ref(true),
|
||||||
IsStarred: ref(true),
|
IsStarred: ref(true),
|
||||||
},
|
},
|
||||||
pagination.PageInput{SortBy: pagination.AlphabeticAsc},
|
pagination.PageInput{SortBy: pagination.AlphabeticAsc}, mocks.CveInfoMock{}, skipCVE,
|
||||||
)
|
)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(len(reposSum), ShouldEqual, 2)
|
So(len(reposSum), ShouldEqual, 2)
|
||||||
So(*reposSum[0].Name, ShouldResemble, "repo1-only-images")
|
So(*reposSum[0].Name, ShouldResemble, "repo1-only-images")
|
||||||
So(*reposSum[1].Name, ShouldResemble, "repo3-only-multiarch")
|
So(*reposSum[1].Name, ShouldResemble, "repo3-only-multiarch")
|
||||||
So(pageInfo.ItemCount, ShouldEqual, 2)
|
So(pageInfo.ItemCount, ShouldEqual, 2)
|
||||||
|
So(pageInfo.ItemCount, ShouldEqual, 2)
|
||||||
|
So(pageInfo.ItemCount, ShouldEqual, 2)
|
||||||
|
So(pageInfo.ItemCount, ShouldEqual, 2)
|
||||||
|
|
||||||
reposSum, pageInfo, err = convert.PaginatedRepoMeta2RepoSummaries(
|
reposSum, pageInfo, err = convert.PaginatedRepoMeta2RepoSummaries(
|
||||||
ctx, reposMeta, manifestMetaMap, indexDataMap, skipCVE, mocks.CveInfoMock{},
|
ctx, repoMetaList, imageMeta,
|
||||||
mTypes.Filter{
|
mTypes.Filter{
|
||||||
Os: []*string{ref("good-os")},
|
Os: []*string{ref("good-os")},
|
||||||
Arch: []*string{ref("good-arch")},
|
Arch: []*string{ref("good-arch")},
|
||||||
@ -520,18 +377,18 @@ func TestPaginatedConvert(t *testing.T) {
|
|||||||
IsStarred: ref(true),
|
IsStarred: ref(true),
|
||||||
HasToBeSigned: ref(true),
|
HasToBeSigned: ref(true),
|
||||||
},
|
},
|
||||||
pagination.PageInput{SortBy: pagination.AlphabeticAsc},
|
pagination.PageInput{SortBy: pagination.AlphabeticAsc}, mocks.CveInfoMock{}, skipCVE,
|
||||||
)
|
)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(len(reposSum), ShouldEqual, 0)
|
So(len(reposSum), ShouldEqual, 0)
|
||||||
So(pageInfo.ItemCount, ShouldEqual, 0)
|
So(pageInfo.ItemCount, ShouldEqual, 0)
|
||||||
|
|
||||||
reposSum, pageInfo, err = convert.PaginatedRepoMeta2RepoSummaries(
|
reposSum, pageInfo, err = convert.PaginatedRepoMeta2RepoSummaries(
|
||||||
ctx, reposMeta, manifestMetaMap, indexDataMap, skipCVE, mocks.CveInfoMock{},
|
ctx, repoMetaList, imageMeta,
|
||||||
mTypes.Filter{
|
mTypes.Filter{
|
||||||
HasToBeSigned: ref(true),
|
HasToBeSigned: ref(true),
|
||||||
},
|
},
|
||||||
pagination.PageInput{SortBy: pagination.AlphabeticAsc},
|
pagination.PageInput{SortBy: pagination.AlphabeticAsc}, mocks.CveInfoMock{}, skipCVE,
|
||||||
)
|
)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(len(reposSum), ShouldEqual, 1)
|
So(len(reposSum), ShouldEqual, 1)
|
||||||
@ -540,8 +397,8 @@ func TestPaginatedConvert(t *testing.T) {
|
|||||||
|
|
||||||
// no filter
|
// no filter
|
||||||
reposSum, pageInfo, err = convert.PaginatedRepoMeta2RepoSummaries(
|
reposSum, pageInfo, err = convert.PaginatedRepoMeta2RepoSummaries(
|
||||||
ctx, reposMeta, manifestMetaMap, indexDataMap, skipCVE, mocks.CveInfoMock{},
|
ctx, repoMetaList, imageMeta,
|
||||||
mTypes.Filter{}, pagination.PageInput{SortBy: pagination.AlphabeticAsc},
|
mTypes.Filter{}, pagination.PageInput{SortBy: pagination.AlphabeticAsc}, mocks.CveInfoMock{}, skipCVE,
|
||||||
)
|
)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(len(reposSum), ShouldEqual, 5)
|
So(len(reposSum), ShouldEqual, 5)
|
||||||
@ -554,8 +411,8 @@ func TestPaginatedConvert(t *testing.T) {
|
|||||||
|
|
||||||
// no filter opposite sorting
|
// no filter opposite sorting
|
||||||
reposSum, pageInfo, err = convert.PaginatedRepoMeta2RepoSummaries(
|
reposSum, pageInfo, err = convert.PaginatedRepoMeta2RepoSummaries(
|
||||||
ctx, reposMeta, manifestMetaMap, indexDataMap, skipCVE, mocks.CveInfoMock{},
|
ctx, repoMetaList, imageMeta,
|
||||||
mTypes.Filter{}, pagination.PageInput{SortBy: pagination.AlphabeticDsc},
|
mTypes.Filter{}, pagination.PageInput{SortBy: pagination.AlphabeticDsc}, mocks.CveInfoMock{}, skipCVE,
|
||||||
)
|
)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(len(reposSum), ShouldEqual, 5)
|
So(len(reposSum), ShouldEqual, 5)
|
||||||
@ -568,14 +425,14 @@ func TestPaginatedConvert(t *testing.T) {
|
|||||||
|
|
||||||
// add pagination
|
// add pagination
|
||||||
reposSum, pageInfo, err = convert.PaginatedRepoMeta2RepoSummaries(
|
reposSum, pageInfo, err = convert.PaginatedRepoMeta2RepoSummaries(
|
||||||
ctx, reposMeta, manifestMetaMap, indexDataMap, skipCVE, mocks.CveInfoMock{},
|
ctx, repoMetaList, imageMeta,
|
||||||
mTypes.Filter{
|
mTypes.Filter{
|
||||||
Os: []*string{ref("good-os")},
|
Os: []*string{ref("good-os")},
|
||||||
Arch: []*string{ref("good-arch")},
|
Arch: []*string{ref("good-arch")},
|
||||||
IsBookmarked: ref(true),
|
IsBookmarked: ref(true),
|
||||||
IsStarred: ref(true),
|
IsStarred: ref(true),
|
||||||
},
|
},
|
||||||
pagination.PageInput{Limit: 1, Offset: 0, SortBy: pagination.AlphabeticAsc},
|
pagination.PageInput{Limit: 1, Offset: 0, SortBy: pagination.AlphabeticAsc}, mocks.CveInfoMock{}, skipCVE,
|
||||||
)
|
)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(len(reposSum), ShouldEqual, 1)
|
So(len(reposSum), ShouldEqual, 1)
|
||||||
@ -584,14 +441,14 @@ func TestPaginatedConvert(t *testing.T) {
|
|||||||
So(pageInfo.TotalCount, ShouldEqual, 2)
|
So(pageInfo.TotalCount, ShouldEqual, 2)
|
||||||
|
|
||||||
reposSum, pageInfo, err = convert.PaginatedRepoMeta2RepoSummaries(
|
reposSum, pageInfo, err = convert.PaginatedRepoMeta2RepoSummaries(
|
||||||
ctx, reposMeta, manifestMetaMap, indexDataMap, skipCVE, mocks.CveInfoMock{},
|
ctx, repoMetaList, imageMeta,
|
||||||
mTypes.Filter{
|
mTypes.Filter{
|
||||||
Os: []*string{ref("good-os")},
|
Os: []*string{ref("good-os")},
|
||||||
Arch: []*string{ref("good-arch")},
|
Arch: []*string{ref("good-arch")},
|
||||||
IsBookmarked: ref(true),
|
IsBookmarked: ref(true),
|
||||||
IsStarred: ref(true),
|
IsStarred: ref(true),
|
||||||
},
|
},
|
||||||
pagination.PageInput{Limit: 1, Offset: 1, SortBy: pagination.AlphabeticAsc},
|
pagination.PageInput{Limit: 1, Offset: 1, SortBy: pagination.AlphabeticAsc}, mocks.CveInfoMock{}, skipCVE,
|
||||||
)
|
)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(len(reposSum), ShouldEqual, 1)
|
So(len(reposSum), ShouldEqual, 1)
|
||||||
@ -601,8 +458,11 @@ func TestPaginatedConvert(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
Convey("PaginatedRepoMeta2ImageSummaries filtering and sorting", t, func() {
|
Convey("PaginatedRepoMeta2ImageSummaries filtering and sorting", t, func() {
|
||||||
imgSum, pageInfo, err := convert.PaginatedRepoMeta2ImageSummaries(
|
fullImageMetaList, err := metaDB.FilterTags(ctx, mTypes.AcceptAllRepoTag, mTypes.AcceptAllImageMeta)
|
||||||
ctx, reposMeta, manifestMetaMap, indexDataMap, skipCVE, mocks.CveInfoMock{},
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
imgSum, pageInfo, err := convert.PaginatedFullImageMeta2ImageSummaries(
|
||||||
|
ctx, fullImageMetaList, skipCVE, mocks.CveInfoMock{},
|
||||||
mTypes.Filter{
|
mTypes.Filter{
|
||||||
Os: []*string{ref("good-os")},
|
Os: []*string{ref("good-os")},
|
||||||
Arch: []*string{ref("good-arch")},
|
Arch: []*string{ref("good-arch")},
|
||||||
@ -624,8 +484,8 @@ func TestPaginatedConvert(t *testing.T) {
|
|||||||
So(pageInfo.ItemCount, ShouldEqual, 5)
|
So(pageInfo.ItemCount, ShouldEqual, 5)
|
||||||
|
|
||||||
// add page of size 2
|
// add page of size 2
|
||||||
imgSum, pageInfo, err = convert.PaginatedRepoMeta2ImageSummaries(
|
imgSum, pageInfo, err = convert.PaginatedFullImageMeta2ImageSummaries(
|
||||||
ctx, reposMeta, manifestMetaMap, indexDataMap, skipCVE, mocks.CveInfoMock{},
|
ctx, fullImageMetaList, skipCVE, mocks.CveInfoMock{},
|
||||||
mTypes.Filter{
|
mTypes.Filter{
|
||||||
Os: []*string{ref("good-os")},
|
Os: []*string{ref("good-os")},
|
||||||
Arch: []*string{ref("good-arch")},
|
Arch: []*string{ref("good-arch")},
|
||||||
@ -642,8 +502,8 @@ func TestPaginatedConvert(t *testing.T) {
|
|||||||
So(pageInfo.TotalCount, ShouldEqual, 5)
|
So(pageInfo.TotalCount, ShouldEqual, 5)
|
||||||
|
|
||||||
// next page
|
// next page
|
||||||
imgSum, pageInfo, err = convert.PaginatedRepoMeta2ImageSummaries(
|
imgSum, pageInfo, err = convert.PaginatedFullImageMeta2ImageSummaries(
|
||||||
ctx, reposMeta, manifestMetaMap, indexDataMap, skipCVE, mocks.CveInfoMock{},
|
ctx, fullImageMetaList, skipCVE, mocks.CveInfoMock{},
|
||||||
mTypes.Filter{
|
mTypes.Filter{
|
||||||
Os: []*string{ref("good-os")},
|
Os: []*string{ref("good-os")},
|
||||||
Arch: []*string{ref("good-arch")},
|
Arch: []*string{ref("good-arch")},
|
||||||
@ -660,8 +520,8 @@ func TestPaginatedConvert(t *testing.T) {
|
|||||||
So(pageInfo.TotalCount, ShouldEqual, 5)
|
So(pageInfo.TotalCount, ShouldEqual, 5)
|
||||||
|
|
||||||
// last page
|
// last page
|
||||||
imgSum, pageInfo, err = convert.PaginatedRepoMeta2ImageSummaries(
|
imgSum, pageInfo, err = convert.PaginatedFullImageMeta2ImageSummaries(
|
||||||
ctx, reposMeta, manifestMetaMap, indexDataMap, skipCVE, mocks.CveInfoMock{},
|
ctx, fullImageMetaList, skipCVE, mocks.CveInfoMock{},
|
||||||
mTypes.Filter{
|
mTypes.Filter{
|
||||||
Os: []*string{ref("good-os")},
|
Os: []*string{ref("good-os")},
|
||||||
Arch: []*string{ref("good-arch")},
|
Arch: []*string{ref("good-arch")},
|
||||||
@ -676,8 +536,8 @@ func TestPaginatedConvert(t *testing.T) {
|
|||||||
So(pageInfo.TotalCount, ShouldEqual, 5)
|
So(pageInfo.TotalCount, ShouldEqual, 5)
|
||||||
|
|
||||||
// has to be signed
|
// has to be signed
|
||||||
imgSum, pageInfo, err = convert.PaginatedRepoMeta2ImageSummaries(
|
imgSum, pageInfo, err = convert.PaginatedFullImageMeta2ImageSummaries(
|
||||||
ctx, reposMeta, manifestMetaMap, indexDataMap, skipCVE, mocks.CveInfoMock{},
|
ctx, fullImageMetaList, skipCVE, mocks.CveInfoMock{},
|
||||||
mTypes.Filter{
|
mTypes.Filter{
|
||||||
Os: []*string{ref("good-os")},
|
Os: []*string{ref("good-os")},
|
||||||
Arch: []*string{ref("good-arch")},
|
Arch: []*string{ref("good-arch")},
|
||||||
@ -697,6 +557,16 @@ func TestIndexAnnotations(t *testing.T) {
|
|||||||
Convey("Test ImageIndex2ImageSummary annotations logic", t, func() {
|
Convey("Test ImageIndex2ImageSummary annotations logic", t, func() {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
|
||||||
|
driver, err := boltdb.GetBoltDriver(boltdb.DBParameters{RootDir: tempDir})
|
||||||
|
if err != nil {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
metaDB, err := boltdb.New(driver, log.NewLogger("debug", ""))
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
configLabels := map[string]string{
|
configLabels := map[string]string{
|
||||||
ispec.AnnotationDescription: "ConfigDescription",
|
ispec.AnnotationDescription: "ConfigDescription",
|
||||||
ispec.AnnotationLicenses: "ConfigLicenses",
|
ispec.AnnotationLicenses: "ConfigLicenses",
|
||||||
@ -746,17 +616,22 @@ func TestIndexAnnotations(t *testing.T) {
|
|||||||
[]Image{imageWithManifestAndConfigAnnotations},
|
[]Image{imageWithManifestAndConfigAnnotations},
|
||||||
).Annotations(indexAnnotations).Build()
|
).Annotations(indexAnnotations).Build()
|
||||||
|
|
||||||
repoMeta, manifestMetadata, indexData := ociutils.GetMetadataForRepos(ociutils.Repo{
|
ctx, err = ociutils.InitializeTestMetaDB(ctx, metaDB,
|
||||||
|
ociutils.Repo{
|
||||||
Name: "repo",
|
Name: "repo",
|
||||||
MultiArchImages: []ociutils.RepoMultiArchImage{
|
MultiArchImages: []ociutils.RepoMultiArchImage{
|
||||||
{MultiarchImage: indexWithAnnotations, Tag: "tag"},
|
{MultiarchImage: indexWithAnnotations, Reference: "tag"},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
digest := indexWithAnnotations.Digest()
|
repoMeta, err := metaDB.GetRepoMeta(ctx, "repo")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
imageMeta, err := metaDB.FilterImageMeta(ctx, []string{indexWithAnnotations.DigestStr()})
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
imageSummary, _, err := convert.ImageIndex2ImageSummary(ctx, "repo", "tag", digest, repoMeta[0],
|
imageSummary, _, err := convert.ImageIndex2ImageSummary(ctx, convert.GetFullImageMeta("tag", repoMeta,
|
||||||
indexData[digest.String()], manifestMetadata)
|
imageMeta[indexWithAnnotations.DigestStr()]))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(*imageSummary.Description, ShouldResemble, "IndexDescription")
|
So(*imageSummary.Description, ShouldResemble, "IndexDescription")
|
||||||
So(*imageSummary.Licenses, ShouldResemble, "IndexLicenses")
|
So(*imageSummary.Licenses, ShouldResemble, "IndexLicenses")
|
||||||
@ -766,19 +641,30 @@ func TestIndexAnnotations(t *testing.T) {
|
|||||||
So(*imageSummary.Vendor, ShouldResemble, "IndexVendor")
|
So(*imageSummary.Vendor, ShouldResemble, "IndexVendor")
|
||||||
So(*imageSummary.Authors, ShouldResemble, "IndexAuthors")
|
So(*imageSummary.Authors, ShouldResemble, "IndexAuthors")
|
||||||
|
|
||||||
|
err = metaDB.ResetDB()
|
||||||
|
So(err, ShouldBeNil)
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
indexWithManifestAndConfigAnnotations := CreateMultiarchWith().Images(
|
indexWithManifestAndConfigAnnotations := CreateMultiarchWith().Images(
|
||||||
[]Image{imageWithManifestAndConfigAnnotations, CreateRandomImage(), CreateRandomImage()},
|
[]Image{imageWithManifestAndConfigAnnotations, CreateRandomImage(), CreateRandomImage()},
|
||||||
).Build()
|
).Build()
|
||||||
|
|
||||||
repoMeta, manifestMetadata, indexData = ociutils.GetMetadataForRepos(ociutils.Repo{
|
ctx, err = ociutils.InitializeTestMetaDB(ctx, metaDB, ociutils.Repo{
|
||||||
Name: "repo",
|
Name: "repo",
|
||||||
MultiArchImages: []ociutils.RepoMultiArchImage{{MultiarchImage: indexWithManifestAndConfigAnnotations}},
|
MultiArchImages: []ociutils.RepoMultiArchImage{
|
||||||
|
{MultiarchImage: indexWithManifestAndConfigAnnotations, Reference: "tag"},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
digest = indexWithManifestAndConfigAnnotations.Digest()
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
imageSummary, _, err = convert.ImageIndex2ImageSummary(ctx, "repo", "tag", digest,
|
digest := indexWithManifestAndConfigAnnotations.DigestStr()
|
||||||
repoMeta[0], indexData[digest.String()], manifestMetadata)
|
|
||||||
|
repoMeta, err = metaDB.GetRepoMeta(ctx, "repo")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
imageMeta, err = metaDB.FilterImageMeta(ctx, []string{digest})
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
imageSummary, _, err = convert.ImageIndex2ImageSummary(ctx, convert.GetFullImageMeta("tag", repoMeta,
|
||||||
|
imageMeta[digest]))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(*imageSummary.Description, ShouldResemble, "ManifestDescription")
|
So(*imageSummary.Description, ShouldResemble, "ManifestDescription")
|
||||||
So(*imageSummary.Licenses, ShouldResemble, "ManifestLicenses")
|
So(*imageSummary.Licenses, ShouldResemble, "ManifestLicenses")
|
||||||
@ -787,19 +673,31 @@ func TestIndexAnnotations(t *testing.T) {
|
|||||||
So(*imageSummary.Documentation, ShouldResemble, "ManifestDocumentation")
|
So(*imageSummary.Documentation, ShouldResemble, "ManifestDocumentation")
|
||||||
So(*imageSummary.Vendor, ShouldResemble, "ManifestVendor")
|
So(*imageSummary.Vendor, ShouldResemble, "ManifestVendor")
|
||||||
So(*imageSummary.Authors, ShouldResemble, "ManifestAuthors")
|
So(*imageSummary.Authors, ShouldResemble, "ManifestAuthors")
|
||||||
|
|
||||||
|
err = metaDB.ResetDB()
|
||||||
|
So(err, ShouldBeNil)
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
indexWithConfigAnnotations := CreateMultiarchWith().Images(
|
indexWithConfigAnnotations := CreateMultiarchWith().Images(
|
||||||
[]Image{imageWithConfigAnnotations, CreateRandomImage(), CreateRandomImage()},
|
[]Image{imageWithConfigAnnotations, CreateRandomImage(), CreateRandomImage()},
|
||||||
).Build()
|
).Build()
|
||||||
|
|
||||||
repoMeta, manifestMetadata, indexData = ociutils.GetMetadataForRepos(ociutils.Repo{
|
ctx, err = ociutils.InitializeTestMetaDB(ctx, metaDB, ociutils.Repo{
|
||||||
Name: "repo",
|
Name: "repo",
|
||||||
MultiArchImages: []ociutils.RepoMultiArchImage{{MultiarchImage: indexWithConfigAnnotations, Tag: "tag"}},
|
MultiArchImages: []ociutils.RepoMultiArchImage{
|
||||||
|
{MultiarchImage: indexWithConfigAnnotations, Reference: "tag"},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
digest = indexWithConfigAnnotations.Digest()
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
imageSummary, _, err = convert.ImageIndex2ImageSummary(ctx, "repo", "tag", digest,
|
digest = indexWithConfigAnnotations.DigestStr()
|
||||||
repoMeta[0], indexData[digest.String()], manifestMetadata)
|
|
||||||
|
repoMeta, err = metaDB.GetRepoMeta(ctx, "repo")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
imageMeta, err = metaDB.FilterImageMeta(ctx, []string{digest})
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
imageSummary, _, err = convert.ImageIndex2ImageSummary(ctx, convert.GetFullImageMeta("tag", repoMeta,
|
||||||
|
imageMeta[digest]))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(*imageSummary.Description, ShouldResemble, "ConfigDescription")
|
So(*imageSummary.Description, ShouldResemble, "ConfigDescription")
|
||||||
So(*imageSummary.Licenses, ShouldResemble, "ConfigLicenses")
|
So(*imageSummary.Licenses, ShouldResemble, "ConfigLicenses")
|
||||||
@ -808,6 +706,9 @@ func TestIndexAnnotations(t *testing.T) {
|
|||||||
So(*imageSummary.Documentation, ShouldResemble, "ConfigDocumentation")
|
So(*imageSummary.Documentation, ShouldResemble, "ConfigDocumentation")
|
||||||
So(*imageSummary.Vendor, ShouldResemble, "ConfigVendor")
|
So(*imageSummary.Vendor, ShouldResemble, "ConfigVendor")
|
||||||
So(*imageSummary.Authors, ShouldResemble, "ConfigAuthors")
|
So(*imageSummary.Authors, ShouldResemble, "ConfigAuthors")
|
||||||
|
|
||||||
|
err = metaDB.ResetDB()
|
||||||
|
So(err, ShouldBeNil)
|
||||||
//--------------------------------------------------------
|
//--------------------------------------------------------
|
||||||
|
|
||||||
indexWithMixAnnotations := CreateMultiarchWith().Images(
|
indexWithMixAnnotations := CreateMultiarchWith().Images(
|
||||||
@ -834,14 +735,23 @@ func TestIndexAnnotations(t *testing.T) {
|
|||||||
},
|
},
|
||||||
).Build()
|
).Build()
|
||||||
|
|
||||||
repoMeta, manifestMetadata, indexData = ociutils.GetMetadataForRepos(ociutils.Repo{
|
ctx, err = ociutils.InitializeTestMetaDB(ctx, metaDB, ociutils.Repo{
|
||||||
Name: "repo",
|
Name: "repo",
|
||||||
MultiArchImages: []ociutils.RepoMultiArchImage{{MultiarchImage: indexWithMixAnnotations, Tag: "tag"}},
|
MultiArchImages: []ociutils.RepoMultiArchImage{
|
||||||
|
{MultiarchImage: indexWithMixAnnotations, Reference: "tag"},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
digest = indexWithMixAnnotations.Digest()
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
imageSummary, _, err = convert.ImageIndex2ImageSummary(ctx, "repo", "tag", digest,
|
digest = indexWithMixAnnotations.DigestStr()
|
||||||
repoMeta[0], indexData[digest.String()], manifestMetadata)
|
|
||||||
|
repoMeta, err = metaDB.GetRepoMeta(ctx, "repo")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
imageMeta, err = metaDB.FilterImageMeta(ctx, []string{digest})
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
imageSummary, _, err = convert.ImageIndex2ImageSummary(ctx, convert.GetFullImageMeta("tag", repoMeta,
|
||||||
|
imageMeta[digest]))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(*imageSummary.Description, ShouldResemble, "ConfigDescription")
|
So(*imageSummary.Description, ShouldResemble, "ConfigDescription")
|
||||||
So(*imageSummary.Licenses, ShouldResemble, "ConfigLicenses")
|
So(*imageSummary.Licenses, ShouldResemble, "ConfigLicenses")
|
||||||
@ -851,17 +761,28 @@ func TestIndexAnnotations(t *testing.T) {
|
|||||||
So(*imageSummary.Documentation, ShouldResemble, "IndexDocumentation")
|
So(*imageSummary.Documentation, ShouldResemble, "IndexDocumentation")
|
||||||
So(*imageSummary.Source, ShouldResemble, "IndexSource")
|
So(*imageSummary.Source, ShouldResemble, "IndexSource")
|
||||||
|
|
||||||
|
err = metaDB.ResetDB()
|
||||||
|
So(err, ShouldBeNil)
|
||||||
//--------------------------------------------------------
|
//--------------------------------------------------------
|
||||||
indexWithNoAnnotations := CreateRandomMultiarch()
|
indexWithNoAnnotations := CreateRandomMultiarch()
|
||||||
|
|
||||||
repoMeta, manifestMetadata, indexData = ociutils.GetMetadataForRepos(ociutils.Repo{
|
ctx, err = ociutils.InitializeTestMetaDB(ctx, metaDB, ociutils.Repo{
|
||||||
Name: "repo",
|
Name: "repo",
|
||||||
MultiArchImages: []ociutils.RepoMultiArchImage{{MultiarchImage: indexWithNoAnnotations, Tag: "tag"}},
|
MultiArchImages: []ociutils.RepoMultiArchImage{
|
||||||
|
{MultiarchImage: indexWithNoAnnotations, Reference: "tag"},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
digest = indexWithNoAnnotations.Digest()
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
imageSummary, _, err = convert.ImageIndex2ImageSummary(ctx, "repo", "tag", digest,
|
digest = indexWithNoAnnotations.DigestStr()
|
||||||
repoMeta[0], indexData[digest.String()], manifestMetadata)
|
|
||||||
|
repoMeta, err = metaDB.GetRepoMeta(ctx, "repo")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
imageMeta, err = metaDB.FilterImageMeta(ctx, []string{digest})
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
imageSummary, _, err = convert.ImageIndex2ImageSummary(ctx, convert.GetFullImageMeta("tag", repoMeta,
|
||||||
|
imageMeta[digest]))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(*imageSummary.Description, ShouldBeBlank)
|
So(*imageSummary.Description, ShouldBeBlank)
|
||||||
So(*imageSummary.Licenses, ShouldBeBlank)
|
So(*imageSummary.Licenses, ShouldBeBlank)
|
||||||
@ -870,94 +791,8 @@ func TestIndexAnnotations(t *testing.T) {
|
|||||||
So(*imageSummary.Title, ShouldBeBlank)
|
So(*imageSummary.Title, ShouldBeBlank)
|
||||||
So(*imageSummary.Documentation, ShouldBeBlank)
|
So(*imageSummary.Documentation, ShouldBeBlank)
|
||||||
So(*imageSummary.Source, ShouldBeBlank)
|
So(*imageSummary.Source, ShouldBeBlank)
|
||||||
})
|
|
||||||
}
|
err = metaDB.ResetDB()
|
||||||
|
So(err, ShouldBeNil)
|
||||||
func TestDownloadCount(t *testing.T) {
|
|
||||||
Convey("manifest", t, func() {
|
|
||||||
repoMeta, manifestMetaMap, indexDataMap := ociutils.GetMetadataForRepos(
|
|
||||||
ociutils.Repo{
|
|
||||||
Name: "repo",
|
|
||||||
Images: []ociutils.RepoImage{
|
|
||||||
{
|
|
||||||
Image: CreateRandomImage(),
|
|
||||||
Tag: "10-downloads",
|
|
||||||
Statistics: mTypes.DescriptorStatistics{
|
|
||||||
DownloadCount: 10,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
repoSummary := convert.RepoMeta2RepoSummary(context.Background(), repoMeta[0], manifestMetaMap, indexDataMap)
|
|
||||||
So(*repoSummary.DownloadCount, ShouldEqual, 10)
|
|
||||||
So(*repoSummary.NewestImage.DownloadCount, ShouldEqual, 10)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("index", t, func() {
|
|
||||||
img1, img2, img3 := CreateRandomImage(), CreateRandomImage(), CreateRandomImage()
|
|
||||||
multiArch := CreateMultiarchWith().Images([]Image{img1, img2, img3}).Build()
|
|
||||||
|
|
||||||
repoMeta, manifestMetaMap, indexDataMap := ociutils.GetMetadataForRepos(
|
|
||||||
ociutils.Repo{
|
|
||||||
Name: "repo",
|
|
||||||
MultiArchImages: []ociutils.RepoMultiArchImage{
|
|
||||||
{
|
|
||||||
MultiarchImage: multiArch,
|
|
||||||
Tag: "160-multiarch",
|
|
||||||
ImageStatistics: map[string]mTypes.DescriptorStatistics{
|
|
||||||
img1.DigestStr(): {DownloadCount: 10},
|
|
||||||
img2.DigestStr(): {DownloadCount: 20},
|
|
||||||
img3.DigestStr(): {DownloadCount: 30},
|
|
||||||
multiArch.DigestStr(): {DownloadCount: 100},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
repoSummary := convert.RepoMeta2RepoSummary(context.Background(), repoMeta[0], manifestMetaMap, indexDataMap)
|
|
||||||
So(*repoSummary.DownloadCount, ShouldEqual, 100)
|
|
||||||
So(*repoSummary.NewestImage.DownloadCount, ShouldEqual, 100)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("index + manifest mixed", t, func() {
|
|
||||||
img1 := CreateRandomImage()
|
|
||||||
img2 := CreateRandomImage()
|
|
||||||
img3 := CreateImageWith().DefaultLayers().ImageConfig(
|
|
||||||
ispec.Image{Created: DateRef(2020, 1, 1, 1, 1, 1, 0, time.UTC)},
|
|
||||||
).Build()
|
|
||||||
|
|
||||||
multiArch := CreateMultiarchWith().Images([]Image{img1, img2, img3}).Build()
|
|
||||||
|
|
||||||
repoMeta, manifestMetaMap, indexDataMap := ociutils.GetMetadataForRepos(
|
|
||||||
ociutils.Repo{
|
|
||||||
Name: "repo",
|
|
||||||
Images: []ociutils.RepoImage{
|
|
||||||
{
|
|
||||||
Image: CreateRandomImage(),
|
|
||||||
Tag: "5-downloads",
|
|
||||||
Statistics: mTypes.DescriptorStatistics{DownloadCount: 5},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
MultiArchImages: []ociutils.RepoMultiArchImage{
|
|
||||||
{
|
|
||||||
MultiarchImage: multiArch,
|
|
||||||
Tag: "160-multiarch",
|
|
||||||
ImageStatistics: map[string]mTypes.DescriptorStatistics{
|
|
||||||
img1.DigestStr(): {DownloadCount: 10},
|
|
||||||
img2.DigestStr(): {DownloadCount: 20},
|
|
||||||
img3.DigestStr(): {DownloadCount: 30},
|
|
||||||
multiArch.DigestStr(): {DownloadCount: 100},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
repoSummary := convert.RepoMeta2RepoSummary(context.Background(), repoMeta[0], manifestMetaMap, indexDataMap)
|
|
||||||
So(*repoSummary.DownloadCount, ShouldEqual, 105)
|
|
||||||
So(*repoSummary.NewestImage.DownloadCount, ShouldEqual, 100)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -9,19 +9,6 @@ import (
|
|||||||
"zotregistry.io/zot/pkg/extensions/search/gql_generated"
|
"zotregistry.io/zot/pkg/extensions/search/gql_generated"
|
||||||
)
|
)
|
||||||
|
|
||||||
// updateRepoBlobsMap adds all the image blobs and their respective size to the repo blobs map
|
|
||||||
// and returnes the total size of the image.
|
|
||||||
func updateRepoBlobsMap(imageBlobs map[string]int64, repoBlob2Size map[string]int64) int64 {
|
|
||||||
imgSize := int64(0)
|
|
||||||
|
|
||||||
for digest, size := range imageBlobs {
|
|
||||||
repoBlob2Size[digest] = size
|
|
||||||
imgSize += size
|
|
||||||
}
|
|
||||||
|
|
||||||
return imgSize
|
|
||||||
}
|
|
||||||
|
|
||||||
func getLayersSummaries(manifestContent ispec.Manifest) []*gql_generated.LayerSummary {
|
func getLayersSummaries(manifestContent ispec.Manifest) []*gql_generated.LayerSummary {
|
||||||
layers := make([]*gql_generated.LayerSummary, 0, len(manifestContent.Layers))
|
layers := make([]*gql_generated.LayerSummary, 0, len(manifestContent.Layers))
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package cveinfo
|
package cveinfo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"context"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -9,6 +9,7 @@ import (
|
|||||||
godigest "github.com/opencontainers/go-digest"
|
godigest "github.com/opencontainers/go-digest"
|
||||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
|
||||||
|
zerr "zotregistry.io/zot/errors"
|
||||||
zcommon "zotregistry.io/zot/pkg/common"
|
zcommon "zotregistry.io/zot/pkg/common"
|
||||||
cvemodel "zotregistry.io/zot/pkg/extensions/search/cve/model"
|
cvemodel "zotregistry.io/zot/pkg/extensions/search/cve/model"
|
||||||
"zotregistry.io/zot/pkg/extensions/search/cve/trivy"
|
"zotregistry.io/zot/pkg/extensions/search/cve/trivy"
|
||||||
@ -57,7 +58,7 @@ func NewCVEInfo(scanner Scanner, metaDB mTypes.MetaDB, log log.Logger) *BaseCveI
|
|||||||
func (cveinfo BaseCveInfo) GetImageListForCVE(repo, cveID string) ([]cvemodel.TagInfo, error) {
|
func (cveinfo BaseCveInfo) GetImageListForCVE(repo, cveID string) ([]cvemodel.TagInfo, error) {
|
||||||
imgList := make([]cvemodel.TagInfo, 0)
|
imgList := make([]cvemodel.TagInfo, 0)
|
||||||
|
|
||||||
repoMeta, err := cveinfo.MetaDB.GetRepoMeta(repo)
|
repoMeta, err := cveinfo.MetaDB.GetRepoMeta(context.Background(), repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cveinfo.Log.Error().Err(err).Str("repository", repo).Str("cve-id", cveID).
|
cveinfo.Log.Error().Err(err).Str("repository", repo).Str("cve-id", cveID).
|
||||||
Msg("unable to get list of tags from repo")
|
Msg("unable to get list of tags from repo")
|
||||||
@ -105,7 +106,7 @@ func (cveinfo BaseCveInfo) GetImageListForCVE(repo, cveID string) ([]cvemodel.Ta
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cveinfo BaseCveInfo) GetImageListWithCVEFixed(repo, cveID string) ([]cvemodel.TagInfo, error) {
|
func (cveinfo BaseCveInfo) GetImageListWithCVEFixed(repo, cveID string) ([]cvemodel.TagInfo, error) {
|
||||||
repoMeta, err := cveinfo.MetaDB.GetRepoMeta(repo)
|
repoMeta, err := cveinfo.MetaDB.GetRepoMeta(context.Background(), repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cveinfo.Log.Error().Err(err).Str("repository", repo).Str("cve-id", cveID).
|
cveinfo.Log.Error().Err(err).Str("repository", repo).Str("cve-id", cveID).
|
||||||
Msg("unable to get list of tags from repo")
|
Msg("unable to get list of tags from repo")
|
||||||
@ -287,19 +288,16 @@ func getIndexContent(metaDB mTypes.MetaDB, indexDigestStr string) (ispec.Index,
|
|||||||
return ispec.Index{}, err
|
return ispec.Index{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
indexData, err := metaDB.GetIndexData(indexDigest)
|
indexData, err := metaDB.GetImageMeta(indexDigest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ispec.Index{}, err
|
return ispec.Index{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var indexContent ispec.Index
|
if indexData.Index == nil {
|
||||||
|
return ispec.Index{}, zerr.ErrUnexpectedMediaType
|
||||||
err = json.Unmarshal(indexData.IndexBlob, &indexContent)
|
|
||||||
if err != nil {
|
|
||||||
return ispec.Index{}, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return indexContent, nil
|
return *indexData.Index, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getConfigAndDigest(metaDB mTypes.MetaDB, manifestDigestStr string) (ispec.Image, godigest.Digest, error) {
|
func getConfigAndDigest(metaDB mTypes.MetaDB, manifestDigestStr string) (ispec.Image, godigest.Digest, error) {
|
||||||
@ -308,17 +306,17 @@ func getConfigAndDigest(metaDB mTypes.MetaDB, manifestDigestStr string) (ispec.I
|
|||||||
return ispec.Image{}, "", err
|
return ispec.Image{}, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
manifestData, err := metaDB.GetManifestData(manifestDigest)
|
manifestData, err := metaDB.GetImageMeta(manifestDigest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ispec.Image{}, "", err
|
return ispec.Image{}, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
var configContent ispec.Image
|
// we'll fail the execution if the config is not compatible with ispec.Image because we can't scan this type of images.
|
||||||
|
if manifestData.Manifests[0].Manifest.Config.MediaType != ispec.MediaTypeImageConfig {
|
||||||
|
return ispec.Image{}, "", zerr.ErrUnexpectedMediaType
|
||||||
|
}
|
||||||
|
|
||||||
// we'll fail the execution if the config is not compatibe with ispec.Image because we can't scan this type of images.
|
return manifestData.Manifests[0].Config, manifestDigest, err
|
||||||
err = json.Unmarshal(manifestData.ConfigBlob, &configContent)
|
|
||||||
|
|
||||||
return configContent, manifestDigest, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterCVEList(cveMap map[string]cvemodel.CVE, searchedCVE string, pageFinder *CvePageFinder) {
|
func filterCVEList(cveMap map[string]cvemodel.CVE, searchedCVE string, pageFinder *CvePageFinder) {
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
package cveinfo_test
|
package cveinfo_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -385,8 +386,8 @@ func TestImageFormat(t *testing.T) {
|
|||||||
log := log.NewLogger("debug", "")
|
log := log.NewLogger("debug", "")
|
||||||
|
|
||||||
metaDB := &mocks.MetaDBMock{
|
metaDB := &mocks.MetaDBMock{
|
||||||
GetRepoMetaFn: func(repo string) (mTypes.RepoMetadata, error) {
|
GetRepoMetaFn: func(ctx context.Context, repo string) (mTypes.RepoMeta, error) {
|
||||||
return mTypes.RepoMetadata{
|
return mTypes.RepoMeta{
|
||||||
Tags: map[string]mTypes.Descriptor{
|
Tags: map[string]mTypes.Descriptor{
|
||||||
"tag": {
|
"tag": {
|
||||||
MediaType: ispec.MediaTypeImageIndex,
|
MediaType: ispec.MediaTypeImageIndex,
|
||||||
@ -395,8 +396,12 @@ func TestImageFormat(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
GetIndexDataFn: func(indexDigest godigest.Digest) (mTypes.IndexData, error) {
|
GetImageMetaFn: func(digest godigest.Digest) (mTypes.ImageMeta, error) {
|
||||||
return mTypes.IndexData{IndexBlob: []byte(`{}`)}, nil
|
return mTypes.ImageMeta{
|
||||||
|
MediaType: ispec.MediaTypeImageIndex,
|
||||||
|
Digest: godigest.FromString("digest"),
|
||||||
|
Index: &ispec.Index{},
|
||||||
|
}, nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
storeController := storage.StoreController{
|
storeController := storage.StoreController{
|
||||||
@ -765,73 +770,32 @@ func TestCVEStruct(t *testing.T) { //nolint:gocyclo
|
|||||||
image11 := CreateImageWith().DefaultLayers().
|
image11 := CreateImageWith().DefaultLayers().
|
||||||
ImageConfig(ispec.Image{Created: DateRef(2008, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
ImageConfig(ispec.Image{Created: DateRef(2008, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
||||||
|
|
||||||
repoMeta11 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference(repo1, "0.1.0", image11.AsImageMeta())
|
||||||
ManifestBlob: image11.ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: image11.ConfigDescriptor.Data,
|
|
||||||
DownloadCount: 0,
|
|
||||||
Signatures: mTypes.ManifestSignatures{},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetManifestMeta(repo1, image11.ManifestDescriptor.Digest, repoMeta11)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference(repo1, "0.1.0", image11.ManifestDescriptor.Digest, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
image12 := CreateImageWith().DefaultLayers().
|
image12 := CreateImageWith().DefaultLayers().
|
||||||
ImageConfig(ispec.Image{Created: DateRef(2009, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
ImageConfig(ispec.Image{Created: DateRef(2009, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
||||||
|
|
||||||
repoMeta12 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference(repo1, "1.0.0", image12.AsImageMeta())
|
||||||
ManifestBlob: image12.ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: image12.ConfigDescriptor.Data,
|
|
||||||
DownloadCount: 0,
|
|
||||||
Signatures: mTypes.ManifestSignatures{},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetManifestMeta(repo1, image12.ManifestDescriptor.Digest, repoMeta12)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference(repo1, "1.0.0", image12.ManifestDescriptor.Digest, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
image13 := CreateImageWith().DefaultLayers().
|
image13 := CreateImageWith().DefaultLayers().
|
||||||
ImageConfig(ispec.Image{Created: DateRef(2010, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
ImageConfig(ispec.Image{Created: DateRef(2010, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
||||||
|
|
||||||
repoMeta13 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference(repo1, "1.1.0", image13.AsImageMeta())
|
||||||
ManifestBlob: image13.ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: image13.ConfigDescriptor.Data,
|
|
||||||
DownloadCount: 0,
|
|
||||||
Signatures: mTypes.ManifestSignatures{},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetManifestMeta(repo1, image13.ManifestDescriptor.Digest, repoMeta13)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference(repo1, "1.1.0", image13.ManifestDescriptor.Digest, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
image14 := CreateImageWith().DefaultLayers().
|
image14 := CreateImageWith().DefaultLayers().
|
||||||
ImageConfig(ispec.Image{Created: DateRef(2011, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
ImageConfig(ispec.Image{Created: DateRef(2011, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
||||||
|
|
||||||
repoMeta14 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference(repo1, "1.0.1", image14.AsImageMeta())
|
||||||
ManifestBlob: image14.ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: image14.ConfigDescriptor.Data,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetManifestMeta(repo1, image14.ManifestDescriptor.Digest, repoMeta14)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference(repo1, "1.0.1", image14.ManifestDescriptor.Digest, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// Create metadb data for scannable image with no vulnerabilities
|
// Create metadb data for scannable image with no vulnerabilities
|
||||||
image61 := CreateImageWith().DefaultLayers().
|
image61 := CreateImageWith().DefaultLayers().
|
||||||
ImageConfig(ispec.Image{Created: DateRef(2016, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
ImageConfig(ispec.Image{Created: DateRef(2016, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
||||||
|
|
||||||
repoMeta61 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference(repo6, "1.0.0", image61.AsImageMeta())
|
||||||
ManifestBlob: image61.ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: image61.ConfigDescriptor.Data,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetManifestMeta(repo6, image61.ManifestDescriptor.Digest, repoMeta61)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference(repo6, "1.0.0", image61.ManifestDescriptor.Digest, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// Create metadb data for image not supporting scanning
|
// Create metadb data for image not supporting scanning
|
||||||
@ -841,106 +805,59 @@ func TestCVEStruct(t *testing.T) { //nolint:gocyclo
|
|||||||
Digest: godigest.FromBytes([]byte{10, 10, 10}),
|
Digest: godigest.FromBytes([]byte{10, 10, 10}),
|
||||||
}}).ImageConfig(ispec.Image{Created: DateRef(2009, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
}}).ImageConfig(ispec.Image{Created: DateRef(2009, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
||||||
|
|
||||||
repoMeta21 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference(repo2, "1.0.0", image21.AsImageMeta())
|
||||||
ManifestBlob: image21.ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: image21.ConfigDescriptor.Data,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetManifestMeta(repo2, image21.ManifestDescriptor.Digest, repoMeta21)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference(repo2, "1.0.0", image21.ManifestDescriptor.Digest, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// Create metadb data for invalid images/negative tests
|
// Create metadb data for invalid images/negative tests
|
||||||
manifestBlob31 := []byte("invalid manifest blob")
|
image := CreateRandomImage()
|
||||||
So(err, ShouldBeNil)
|
err = metaDB.SetRepoReference(repo3, "invalid-manifest", image.AsImageMeta())
|
||||||
|
|
||||||
repoMeta31 := mTypes.ManifestMetadata{
|
|
||||||
ManifestBlob: manifestBlob31,
|
|
||||||
}
|
|
||||||
|
|
||||||
digest31 := godigest.FromBytes(manifestBlob31)
|
|
||||||
err = metaDB.SetManifestMeta(repo3, digest31, repoMeta31)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference(repo3, "invalid-manifest", digest31, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
image41 := CreateImageWith().DefaultLayers().
|
image41 := CreateImageWith().DefaultLayers().
|
||||||
CustomConfigBlob([]byte("invalid config blob"), ispec.MediaTypeImageConfig).Build()
|
CustomConfigBlob([]byte("invalid config blob"), ispec.MediaTypeImageConfig).Build()
|
||||||
|
|
||||||
repoMeta41 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference(repo4, "invalid-config", image41.AsImageMeta())
|
||||||
ManifestBlob: image41.ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: image41.ConfigDescriptor.Data,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetManifestMeta(repo4, image41.ManifestDescriptor.Digest, repoMeta41)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference(repo4, "invalid-config", image41.ManifestDescriptor.Digest,
|
|
||||||
ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
digest51 := godigest.FromString("abc8")
|
digest51 := godigest.FromString("abc8")
|
||||||
err = metaDB.SetRepoReference(repo5, "nonexitent-manifest", digest51, ispec.MediaTypeImageManifest)
|
randomImgData := CreateRandomImage().AsImageMeta()
|
||||||
|
randomImgData.Digest = digest51
|
||||||
|
randomImgData.Manifests[0].Digest = digest51
|
||||||
|
err = metaDB.SetRepoReference(repo5, "nonexitent-manifest", randomImgData)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// Create metadb data for scannable image which errors during scan
|
// Create metadb data for scannable image which errors during scan
|
||||||
image71 := CreateImageWith().DefaultLayers().
|
image71 := CreateImageWith().DefaultLayers().
|
||||||
ImageConfig(ispec.Image{Created: DateRef(2000, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
ImageConfig(ispec.Image{Created: DateRef(2000, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
||||||
|
|
||||||
repoMeta71 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference(repo7, "1.0.0", image71.AsImageMeta())
|
||||||
ManifestBlob: image71.ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: image71.ConfigDescriptor.Data,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetManifestMeta(repo7, image71.ManifestDescriptor.Digest, repoMeta71)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference(repo7, "1.0.0", image71.ManifestDescriptor.Digest, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// create multiarch image with vulnerabilities
|
// create multiarch image with vulnerabilities
|
||||||
multiarchImage := CreateRandomMultiarch()
|
multiarchImage := CreateRandomMultiarch()
|
||||||
|
|
||||||
err = metaDB.SetIndexData(
|
err = metaDB.SetRepoReference(repoMultiarch, multiarchImage.Images[0].DigestStr(),
|
||||||
multiarchImage.IndexDescriptor.Digest,
|
multiarchImage.Images[0].AsImageMeta())
|
||||||
mTypes.IndexData{IndexBlob: multiarchImage.IndexDescriptor.Data},
|
|
||||||
)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
err = metaDB.SetManifestData(
|
err = metaDB.SetRepoReference(repoMultiarch, multiarchImage.Images[1].DigestStr(),
|
||||||
multiarchImage.Images[0].ManifestDescriptor.Digest,
|
multiarchImage.Images[1].AsImageMeta())
|
||||||
mTypes.ManifestData{
|
So(err, ShouldBeNil)
|
||||||
ManifestBlob: multiarchImage.Images[0].ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: multiarchImage.Images[0].ConfigDescriptor.Data,
|
err = metaDB.SetRepoReference(repoMultiarch, multiarchImage.Images[2].DigestStr(),
|
||||||
|
multiarchImage.Images[2].AsImageMeta())
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
err = metaDB.SetRepoReference(repoMultiarch, "tagIndex", multiarchImage.AsImageMeta())
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
err = metaDB.SetRepoMeta("repo-with-bad-tag-digest", mTypes.RepoMeta{
|
||||||
|
Name: "repo-with-bad-tag-digest",
|
||||||
|
Tags: map[string]mTypes.Descriptor{
|
||||||
|
"tag": {MediaType: ispec.MediaTypeImageManifest, Digest: godigest.FromString("1").String()},
|
||||||
},
|
},
|
||||||
)
|
})
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
err = metaDB.SetManifestData(
|
|
||||||
multiarchImage.Images[1].ManifestDescriptor.Digest,
|
|
||||||
mTypes.ManifestData{
|
|
||||||
ManifestBlob: multiarchImage.Images[1].ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: multiarchImage.Images[1].ConfigDescriptor.Data,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = metaDB.SetManifestData(
|
|
||||||
multiarchImage.Images[2].ManifestDescriptor.Digest,
|
|
||||||
mTypes.ManifestData{
|
|
||||||
ManifestBlob: multiarchImage.Images[2].ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: multiarchImage.Images[2].ConfigDescriptor.Data,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = metaDB.SetRepoReference(
|
|
||||||
repoMultiarch,
|
|
||||||
"tagIndex",
|
|
||||||
multiarchImage.IndexDescriptor.Digest,
|
|
||||||
ispec.MediaTypeImageIndex,
|
|
||||||
)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
// Keep a record of all the image references / digest pairings
|
// Keep a record of all the image references / digest pairings
|
||||||
// This is normally done in MetaDB, but we want to verify
|
// This is normally done in MetaDB, but we want to verify
|
||||||
// the whole flow, including MetaDB
|
// the whole flow, including MetaDB
|
||||||
@ -966,18 +883,6 @@ func TestCVEStruct(t *testing.T) { //nolint:gocyclo
|
|||||||
image21Media := image21.ManifestDescriptor.MediaType
|
image21Media := image21.ManifestDescriptor.MediaType
|
||||||
image21Name := repo2 + ":1.0.0"
|
image21Name := repo2 + ":1.0.0"
|
||||||
imageMap[image21Name] = image21Digest
|
imageMap[image21Name] = image21Digest
|
||||||
image31Digest := digest31.String()
|
|
||||||
image31Media := ispec.MediaTypeImageManifest
|
|
||||||
image31Name := repo3 + ":invalid-manifest"
|
|
||||||
imageMap[image31Name] = image31Digest
|
|
||||||
image41Digest := image41.ManifestDescriptor.Digest.String()
|
|
||||||
image41Media := image41.ManifestDescriptor.MediaType
|
|
||||||
image41Name := repo4 + ":invalid-config"
|
|
||||||
imageMap[image41Name] = image41Digest
|
|
||||||
image51Digest := digest51.String()
|
|
||||||
image51Media := ispec.MediaTypeImageManifest
|
|
||||||
image51Name := repo5 + ":nonexitent-manifest"
|
|
||||||
imageMap[image51Name] = digest51.String()
|
|
||||||
image61Digest := image61.ManifestDescriptor.Digest.String()
|
image61Digest := image61.ManifestDescriptor.Digest.String()
|
||||||
image61Media := image61.ManifestDescriptor.MediaType
|
image61Media := image61.ManifestDescriptor.MediaType
|
||||||
image61Name := repo6 + ":1.0.0"
|
image61Name := repo6 + ":1.0.0"
|
||||||
@ -1151,7 +1056,7 @@ func TestCVEStruct(t *testing.T) { //nolint:gocyclo
|
|||||||
// Almost same logic compared to actual Trivy specific implementation
|
// Almost same logic compared to actual Trivy specific implementation
|
||||||
imageDir, inputTag := repo, reference
|
imageDir, inputTag := repo, reference
|
||||||
|
|
||||||
repoMeta, err := metaDB.GetRepoMeta(imageDir)
|
repoMeta, err := metaDB.GetRepoMeta(context.Background(), imageDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@ -1174,19 +1079,12 @@ func TestCVEStruct(t *testing.T) { //nolint:gocyclo
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
manifestData, err := metaDB.GetManifestData(manifestDigest)
|
manifestData, err := metaDB.GetImageMeta(manifestDigest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var manifestContent ispec.Manifest
|
for _, imageLayer := range manifestData.Manifests[0].Manifest.Layers {
|
||||||
|
|
||||||
err = json.Unmarshal(manifestData.ManifestBlob, &manifestContent)
|
|
||||||
if err != nil {
|
|
||||||
return false, zerr.ErrScanNotSupported
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, imageLayer := range manifestContent.Layers {
|
|
||||||
switch imageLayer.MediaType {
|
switch imageLayer.MediaType {
|
||||||
case ispec.MediaTypeImageLayerGzip, ispec.MediaTypeImageLayer, string(regTypes.DockerLayer):
|
case ispec.MediaTypeImageLayerGzip, ispec.MediaTypeImageLayer, string(regTypes.DockerLayer):
|
||||||
|
|
||||||
@ -1203,12 +1101,6 @@ func TestCVEStruct(t *testing.T) { //nolint:gocyclo
|
|||||||
if repo == repo2 && digest == image21Digest {
|
if repo == repo2 && digest == image21Digest {
|
||||||
return false, zerr.ErrScanNotSupported
|
return false, zerr.ErrScanNotSupported
|
||||||
}
|
}
|
||||||
if repo == repo3 && digest == image31Digest {
|
|
||||||
return false, zerr.ErrTagMetaNotFound
|
|
||||||
}
|
|
||||||
if repo == repo5 && digest == image51Digest {
|
|
||||||
return false, zerr.ErrManifestDataNotFound
|
|
||||||
}
|
|
||||||
if repo == repo100 {
|
if repo == repo100 {
|
||||||
return false, zerr.ErrRepoMetaNotFound
|
return false, zerr.ErrRepoMetaNotFound
|
||||||
}
|
}
|
||||||
@ -1295,20 +1187,6 @@ func TestCVEStruct(t *testing.T) { //nolint:gocyclo
|
|||||||
So(pageInfo.ItemCount, ShouldEqual, 0)
|
So(pageInfo.ItemCount, ShouldEqual, 0)
|
||||||
So(pageInfo.TotalCount, ShouldEqual, 0)
|
So(pageInfo.TotalCount, ShouldEqual, 0)
|
||||||
|
|
||||||
// Config not valid
|
|
||||||
cveList, pageInfo, err = cveInfo.GetCVEListForImage(repo4, "invalid-config", "", pageInput)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(len(cveList), ShouldEqual, 0)
|
|
||||||
So(pageInfo.ItemCount, ShouldEqual, 0)
|
|
||||||
So(pageInfo.TotalCount, ShouldEqual, 0)
|
|
||||||
|
|
||||||
// Manifest is not found
|
|
||||||
cveList, pageInfo, err = cveInfo.GetCVEListForImage(repo5, "nonexitent-manifest", "", pageInput)
|
|
||||||
So(err, ShouldEqual, zerr.ErrManifestDataNotFound)
|
|
||||||
So(len(cveList), ShouldEqual, 0)
|
|
||||||
So(pageInfo.ItemCount, ShouldEqual, 0)
|
|
||||||
So(pageInfo.TotalCount, ShouldEqual, 0)
|
|
||||||
|
|
||||||
// Scan failed
|
// Scan failed
|
||||||
cveList, pageInfo, err = cveInfo.GetCVEListForImage(repo7, "1.0.0", "", pageInput)
|
cveList, pageInfo, err = cveInfo.GetCVEListForImage(repo7, "1.0.0", "", pageInput)
|
||||||
So(err, ShouldEqual, ErrFailedScan)
|
So(err, ShouldEqual, ErrFailedScan)
|
||||||
@ -1316,6 +1194,13 @@ func TestCVEStruct(t *testing.T) { //nolint:gocyclo
|
|||||||
So(pageInfo.ItemCount, ShouldEqual, 0)
|
So(pageInfo.ItemCount, ShouldEqual, 0)
|
||||||
So(pageInfo.TotalCount, ShouldEqual, 0)
|
So(pageInfo.TotalCount, ShouldEqual, 0)
|
||||||
|
|
||||||
|
// Tag is not found
|
||||||
|
cveList, pageInfo, err = cveInfo.GetCVEListForImage("repo-with-bad-tag-digest", "tag", "", pageInput)
|
||||||
|
So(err, ShouldEqual, zerr.ErrImageMetaNotFound)
|
||||||
|
So(len(cveList), ShouldEqual, 0)
|
||||||
|
So(pageInfo.ItemCount, ShouldEqual, 0)
|
||||||
|
So(pageInfo.TotalCount, ShouldEqual, 0)
|
||||||
|
|
||||||
// Repo is not found
|
// Repo is not found
|
||||||
cveList, pageInfo, err = cveInfo.GetCVEListForImage(repo100, "1.0.0", "", pageInput)
|
cveList, pageInfo, err = cveInfo.GetCVEListForImage(repo100, "1.0.0", "", pageInput)
|
||||||
So(err, ShouldEqual, zerr.ErrRepoMetaNotFound)
|
So(err, ShouldEqual, zerr.ErrRepoMetaNotFound)
|
||||||
@ -1364,24 +1249,6 @@ func TestCVEStruct(t *testing.T) { //nolint:gocyclo
|
|||||||
So(cveSummary.Count, ShouldEqual, 0)
|
So(cveSummary.Count, ShouldEqual, 0)
|
||||||
So(cveSummary.MaxSeverity, ShouldEqual, "")
|
So(cveSummary.MaxSeverity, ShouldEqual, "")
|
||||||
|
|
||||||
// Tag is not found
|
|
||||||
cveSummary, err = cveInfo.GetCVESummaryForImageMedia(repo3, image31Digest, image31Media)
|
|
||||||
So(err, ShouldEqual, zerr.ErrTagMetaNotFound)
|
|
||||||
So(cveSummary.Count, ShouldEqual, 0)
|
|
||||||
So(cveSummary.MaxSeverity, ShouldEqual, "")
|
|
||||||
|
|
||||||
// Config not valid
|
|
||||||
cveSummary, err = cveInfo.GetCVESummaryForImageMedia(repo4, image41Digest, image41Media)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(cveSummary.Count, ShouldEqual, 0)
|
|
||||||
So(cveSummary.MaxSeverity, ShouldEqual, "NONE")
|
|
||||||
|
|
||||||
// Manifest is not found
|
|
||||||
cveSummary, err = cveInfo.GetCVESummaryForImageMedia(repo5, image51Digest, image51Media)
|
|
||||||
So(err, ShouldEqual, zerr.ErrManifestDataNotFound)
|
|
||||||
So(cveSummary.Count, ShouldEqual, 0)
|
|
||||||
So(cveSummary.MaxSeverity, ShouldEqual, "")
|
|
||||||
|
|
||||||
// Scan failed
|
// Scan failed
|
||||||
cveSummary, err = cveInfo.GetCVESummaryForImageMedia(repo5, image71Digest, image71Media)
|
cveSummary, err = cveInfo.GetCVESummaryForImageMedia(repo5, image71Digest, image71Media)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
@ -1430,16 +1297,6 @@ func TestCVEStruct(t *testing.T) { //nolint:gocyclo
|
|||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(len(tagList), ShouldEqual, 0)
|
So(len(tagList), ShouldEqual, 0)
|
||||||
|
|
||||||
// Tag is not found, but we should not error
|
|
||||||
tagList, err = cveInfo.GetImageListWithCVEFixed(repo3, "CVE101")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(len(tagList), ShouldEqual, 0)
|
|
||||||
|
|
||||||
// Manifest is not found, we just consider exclude it from the fixed list
|
|
||||||
tagList, err = cveInfo.GetImageListWithCVEFixed(repo5, "CVE101")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(len(tagList), ShouldEqual, 0)
|
|
||||||
|
|
||||||
// Repo is not found, there could potentially be unaffected tags in the repo
|
// Repo is not found, there could potentially be unaffected tags in the repo
|
||||||
// but we can't access their data
|
// but we can't access their data
|
||||||
tagList, err = cveInfo.GetImageListWithCVEFixed(repo100, "CVE100")
|
tagList, err = cveInfo.GetImageListWithCVEFixed(repo100, "CVE100")
|
||||||
@ -1719,158 +1576,6 @@ func TestFixedTagsWithIndex(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestImageListWithCVEFixedErrors(t *testing.T) {
|
|
||||||
indexDigest := godigest.FromString("index")
|
|
||||||
manifestDigest := "sha256:1111111111111111111111111111111111111111111111111111111111111111"
|
|
||||||
|
|
||||||
Convey("Errors", t, func() {
|
|
||||||
storeController := storage.StoreController{}
|
|
||||||
storeController.DefaultStore = mocks.MockedImageStore{}
|
|
||||||
|
|
||||||
metaDB := mocks.MetaDBMock{}
|
|
||||||
log := log.NewLogger("debug", "")
|
|
||||||
|
|
||||||
Convey("getIndexContent errors", func() {
|
|
||||||
metaDB.GetRepoMetaFn = func(repo string) (mTypes.RepoMetadata, error) {
|
|
||||||
return mTypes.RepoMetadata{
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"tag": {
|
|
||||||
Digest: indexDigest.String(),
|
|
||||||
MediaType: ispec.MediaTypeImageIndex,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
metaDB.GetIndexDataFn = func(indexDigest godigest.Digest) (mTypes.IndexData, error) {
|
|
||||||
return mTypes.IndexData{}, zerr.ErrIndexDataNotFount
|
|
||||||
}
|
|
||||||
|
|
||||||
scanner := cveinfo.NewScanner(storeController, metaDB, "", "", log)
|
|
||||||
cveInfo := cveinfo.NewCVEInfo(scanner, metaDB, log)
|
|
||||||
|
|
||||||
_, err := cveInfo.GetImageListWithCVEFixed("repo", Vulnerability1ID)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("getIndexContent bad indexDigest", func() {
|
|
||||||
metaDB.GetRepoMetaFn = func(repo string) (mTypes.RepoMetadata, error) {
|
|
||||||
return mTypes.RepoMetadata{
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"tag": {
|
|
||||||
Digest: "bad digest",
|
|
||||||
MediaType: ispec.MediaTypeImageIndex,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
metaDB.GetIndexDataFn = func(indexDigest godigest.Digest) (mTypes.IndexData, error) {
|
|
||||||
return mTypes.IndexData{}, zerr.ErrIndexDataNotFount
|
|
||||||
}
|
|
||||||
|
|
||||||
scanner := cveinfo.NewScanner(storeController, metaDB, "", "", log)
|
|
||||||
cveInfo := cveinfo.NewCVEInfo(scanner, metaDB, log)
|
|
||||||
|
|
||||||
_, err := cveInfo.GetImageListWithCVEFixed("repo", Vulnerability1ID)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("getIndexContent bad index content", func() {
|
|
||||||
metaDB.GetRepoMetaFn = func(repo string) (mTypes.RepoMetadata, error) {
|
|
||||||
return mTypes.RepoMetadata{
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"tag": {
|
|
||||||
Digest: indexDigest.String(),
|
|
||||||
MediaType: ispec.MediaTypeImageIndex,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
metaDB.GetIndexDataFn = func(indexDigest godigest.Digest) (mTypes.IndexData, error) {
|
|
||||||
return mTypes.IndexData{IndexBlob: []byte(`bad index`)}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
scanner := cveinfo.NewScanner(storeController, metaDB, "", "", log)
|
|
||||||
cveInfo := cveinfo.NewCVEInfo(scanner, metaDB, log)
|
|
||||||
|
|
||||||
_, err := cveInfo.GetImageListWithCVEFixed("repo", Vulnerability1ID)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("getTagInfoForManifest bad manifest digest", func() {
|
|
||||||
metaDB.GetRepoMetaFn = func(repo string) (mTypes.RepoMetadata, error) {
|
|
||||||
return mTypes.RepoMetadata{
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"tag": {
|
|
||||||
Digest: "bad digest",
|
|
||||||
MediaType: ispec.MediaTypeImageManifest,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
scanner := cveinfo.NewScanner(storeController, metaDB, "", "", log)
|
|
||||||
cveInfo := cveinfo.NewCVEInfo(scanner, metaDB, log)
|
|
||||||
|
|
||||||
_, err := cveInfo.GetImageListWithCVEFixed("repo", Vulnerability1ID)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("getTagInfoForManifest fails for index", func() {
|
|
||||||
metaDB.GetRepoMetaFn = func(repo string) (mTypes.RepoMetadata, error) {
|
|
||||||
return mTypes.RepoMetadata{
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"tag": {
|
|
||||||
Digest: indexDigest.String(),
|
|
||||||
MediaType: ispec.MediaTypeImageIndex,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
metaDB.GetIndexDataFn = func(indexDigest godigest.Digest) (mTypes.IndexData, error) {
|
|
||||||
return mTypes.IndexData{
|
|
||||||
IndexBlob: []byte(fmt.Sprintf(`{
|
|
||||||
"manifests": [
|
|
||||||
{
|
|
||||||
"digest": "%s",
|
|
||||||
"mediaType": "application/vnd.oci.image.manifest.v1+json"
|
|
||||||
}
|
|
||||||
]}`, manifestDigest)),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
metaDB.GetManifestDataFn = func(manifestDigest godigest.Digest) (mTypes.ManifestData, error) {
|
|
||||||
return mTypes.ManifestData{}, zerr.ErrManifestDataNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
scanner := cveinfo.NewScanner(storeController, metaDB, "", "", log)
|
|
||||||
cveInfo := cveinfo.NewCVEInfo(scanner, metaDB, log)
|
|
||||||
|
|
||||||
tagsInfo, err := cveInfo.GetImageListWithCVEFixed("repo", Vulnerability1ID)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(tagsInfo, ShouldBeEmpty)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("media type not supported", func() {
|
|
||||||
metaDB.GetRepoMetaFn = func(repo string) (mTypes.RepoMetadata, error) {
|
|
||||||
return mTypes.RepoMetadata{
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"tag": {
|
|
||||||
Digest: godigest.FromString("media type").String(),
|
|
||||||
MediaType: "bad media type",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
scanner := cveinfo.NewScanner(storeController, metaDB, "", "", log)
|
|
||||||
cveInfo := cveinfo.NewCVEInfo(scanner, metaDB, log)
|
|
||||||
|
|
||||||
tagsInfo, err := cveInfo.GetImageListWithCVEFixed("repo", Vulnerability1ID)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(tagsInfo, ShouldBeEmpty)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetCVESummaryForImageMediaErrors(t *testing.T) {
|
func TestGetCVESummaryForImageMediaErrors(t *testing.T) {
|
||||||
Convey("Errors", t, func() {
|
Convey("Errors", t, func() {
|
||||||
storeController := storage.StoreController{}
|
storeController := storage.StoreController{}
|
||||||
|
@ -4,13 +4,11 @@
|
|||||||
package cveinfo_test
|
package cveinfo_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
godigest "github.com/opencontainers/go-digest"
|
|
||||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
|
||||||
@ -18,7 +16,7 @@ import (
|
|||||||
cvemodel "zotregistry.io/zot/pkg/extensions/search/cve/model"
|
cvemodel "zotregistry.io/zot/pkg/extensions/search/cve/model"
|
||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
"zotregistry.io/zot/pkg/meta/boltdb"
|
"zotregistry.io/zot/pkg/meta/boltdb"
|
||||||
mTypes "zotregistry.io/zot/pkg/meta/types"
|
. "zotregistry.io/zot/pkg/test/image-utils"
|
||||||
"zotregistry.io/zot/pkg/test/mocks"
|
"zotregistry.io/zot/pkg/test/mocks"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -36,70 +34,26 @@ func TestCVEPagination(t *testing.T) {
|
|||||||
// Create metadb data for scannable image with vulnerabilities
|
// Create metadb data for scannable image with vulnerabilities
|
||||||
timeStamp11 := time.Date(2008, 1, 1, 12, 0, 0, 0, time.UTC)
|
timeStamp11 := time.Date(2008, 1, 1, 12, 0, 0, 0, time.UTC)
|
||||||
|
|
||||||
configBlob11, err := json.Marshal(ispec.Image{
|
image := CreateImageWith().
|
||||||
Created: &timeStamp11,
|
Layers([]Layer{{
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
manifestBlob11, err := json.Marshal(ispec.Manifest{
|
|
||||||
Config: ispec.Descriptor{
|
|
||||||
MediaType: ispec.MediaTypeImageConfig,
|
|
||||||
Size: 0,
|
|
||||||
Digest: godigest.FromBytes(configBlob11),
|
|
||||||
},
|
|
||||||
Layers: []ispec.Descriptor{
|
|
||||||
{
|
|
||||||
MediaType: ispec.MediaTypeImageLayerGzip,
|
MediaType: ispec.MediaTypeImageLayerGzip,
|
||||||
Size: 0,
|
Digest: ispec.DescriptorEmptyJSON.Digest,
|
||||||
Digest: godigest.NewDigestFromEncoded(godigest.SHA256, "digest"),
|
Blob: ispec.DescriptorEmptyJSON.Data,
|
||||||
},
|
}}).ImageConfig(ispec.Image{Created: &timeStamp11}).Build()
|
||||||
},
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
repoMeta11 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference("repo1", "0.1.0", image.AsImageMeta())
|
||||||
ManifestBlob: manifestBlob11,
|
|
||||||
ConfigBlob: configBlob11,
|
|
||||||
}
|
|
||||||
|
|
||||||
digest11 := godigest.FromBytes(manifestBlob11)
|
|
||||||
err = metaDB.SetManifestMeta("repo1", digest11, repoMeta11)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference("repo1", "0.1.0", digest11, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
timeStamp12 := time.Date(2009, 1, 1, 12, 0, 0, 0, time.UTC)
|
timeStamp12 := time.Date(2009, 1, 1, 12, 0, 0, 0, time.UTC)
|
||||||
|
|
||||||
configBlob12, err := json.Marshal(ispec.Image{
|
image2 := CreateImageWith().
|
||||||
Created: &timeStamp12,
|
Layers([]Layer{{
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
manifestBlob12, err := json.Marshal(ispec.Manifest{
|
|
||||||
Config: ispec.Descriptor{
|
|
||||||
MediaType: ispec.MediaTypeImageConfig,
|
|
||||||
Size: 0,
|
|
||||||
Digest: godigest.FromBytes(configBlob12),
|
|
||||||
},
|
|
||||||
Layers: []ispec.Descriptor{
|
|
||||||
{
|
|
||||||
MediaType: ispec.MediaTypeImageLayerGzip,
|
MediaType: ispec.MediaTypeImageLayerGzip,
|
||||||
Size: 0,
|
Digest: ispec.DescriptorEmptyJSON.Digest,
|
||||||
Digest: godigest.NewDigestFromEncoded(godigest.SHA256, "digest"),
|
Blob: ispec.DescriptorEmptyJSON.Data,
|
||||||
},
|
}}).ImageConfig(ispec.Image{Created: &timeStamp12}).Build()
|
||||||
},
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
repoMeta12 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference("repo1", "1.0.0", image2.AsImageMeta())
|
||||||
ManifestBlob: manifestBlob12,
|
|
||||||
ConfigBlob: configBlob12,
|
|
||||||
}
|
|
||||||
|
|
||||||
digest12 := godigest.FromBytes(manifestBlob12)
|
|
||||||
err = metaDB.SetManifestMeta("repo1", digest12, repoMeta12)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference("repo1", "1.0.0", digest12, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// MetaDB loaded with initial data, mock the scanner
|
// MetaDB loaded with initial data, mock the scanner
|
||||||
|
@ -4,8 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
godigest "github.com/opencontainers/go-digest"
|
|
||||||
|
|
||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
mTypes "zotregistry.io/zot/pkg/meta/types"
|
mTypes "zotregistry.io/zot/pkg/meta/types"
|
||||||
reqCtx "zotregistry.io/zot/pkg/requestcontext"
|
reqCtx "zotregistry.io/zot/pkg/requestcontext"
|
||||||
@ -43,13 +41,13 @@ type scanTaskGenerator struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gen *scanTaskGenerator) getMatcherFunc() mTypes.FilterFunc {
|
func (gen *scanTaskGenerator) getMatcherFunc() mTypes.FilterFunc {
|
||||||
return func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool {
|
return func(repoMeta mTypes.RepoMeta, imageMeta mTypes.ImageMeta) bool {
|
||||||
// Note this matcher will return information based on scan status of manifests
|
// Note this matcher will return information based on scan status of manifests
|
||||||
// An index scan aggregates results of manifest scans
|
// An index scan aggregates results of manifest scans
|
||||||
// If at least one of its manifests can be scanned,
|
// If at least one of its manifests can be scanned,
|
||||||
// the index and its tag will be returned by the caller function too
|
// the index and its tag will be returned by the caller function too
|
||||||
repoName := repoMeta.Name
|
repoName := repoMeta.Name
|
||||||
manifestDigest := godigest.FromBytes(manifestMeta.ManifestBlob).String()
|
manifestDigest := imageMeta.Digest.String()
|
||||||
|
|
||||||
if gen.isScheduled(manifestDigest) {
|
if gen.isScheduled(manifestDigest) {
|
||||||
// We skip this manifest as it has already scheduled
|
// We skip this manifest as it has already scheduled
|
||||||
@ -121,18 +119,18 @@ func (gen *scanTaskGenerator) Next() (scheduler.Task, error) {
|
|||||||
userAc.SetIsAdmin(true)
|
userAc.SetIsAdmin(true)
|
||||||
ctx := userAc.DeriveContext(context.Background())
|
ctx := userAc.DeriveContext(context.Background())
|
||||||
|
|
||||||
// Obtain a list of repos with unscanned scannable manifests
|
// Obtain a list of repos with un-scanned scannable manifests
|
||||||
// We may implement a method to return just 1 match at some point
|
// We may implement a method to return just 1 match at some point
|
||||||
reposMeta, _, _, err := gen.metaDB.FilterTags(ctx, gen.getMatcherFunc())
|
imageMeta, err := gen.metaDB.FilterTags(ctx, mTypes.AcceptAllRepoTag, gen.getMatcherFunc())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Do not crash the generator for potential repodb inconistencies
|
// Do not crash the generator for potential metadb inconsistencies
|
||||||
// as there may be scannable images not yet scanned
|
// as there may be scannable images not yet scanned
|
||||||
gen.log.Warn().Err(err).Msg("Scheduled CVE scan: error while obtaining repo metadata")
|
gen.log.Warn().Err(err).Msg("Scheduled CVE scan: error while obtaining repo metadata")
|
||||||
}
|
}
|
||||||
|
|
||||||
// no reposMeta are returned, all results are in already in cache
|
// no imageMeta are returned, all results are in already in cache
|
||||||
// or manifests cannot be scanned
|
// or manifests cannot be scanned
|
||||||
if len(reposMeta) == 0 {
|
if len(imageMeta) == 0 {
|
||||||
gen.log.Info().Msg("Scheduled CVE scan: finished for available images")
|
gen.log.Info().Msg("Scheduled CVE scan: finished for available images")
|
||||||
|
|
||||||
gen.done = true
|
gen.done = true
|
||||||
@ -140,23 +138,14 @@ func (gen *scanTaskGenerator) Next() (scheduler.Task, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since reposMeta will always contain just unscanned images we can pick
|
// Since imageMeta will always contain just un-scanned images we can pick
|
||||||
// any repo and any tag out of the resulting matches
|
// any image out of the resulting matches
|
||||||
repoMeta := reposMeta[0]
|
digest := imageMeta[0].Digest.String()
|
||||||
|
|
||||||
var digest string
|
|
||||||
|
|
||||||
// Pick any tag
|
|
||||||
for _, descriptor := range repoMeta.Tags {
|
|
||||||
digest = descriptor.Digest
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark the digest as scheduled so it is skipped on next generator run
|
// Mark the digest as scheduled so it is skipped on next generator run
|
||||||
gen.setScheduled(digest, true)
|
gen.setScheduled(digest, true)
|
||||||
|
|
||||||
return newScanTask(gen, repoMeta.Name, digest), nil
|
return newScanTask(gen, imageMeta[0].Repo, digest), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gen *scanTaskGenerator) IsDone() bool {
|
func (gen *scanTaskGenerator) IsDone() bool {
|
||||||
|
@ -5,7 +5,6 @@ package cveinfo_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@ -69,77 +68,38 @@ func TestScanGeneratorWithMockedData(t *testing.T) { //nolint: gocyclo
|
|||||||
metaDB, err := boltdb.New(boltDriver, log.NewLogger("debug", ""))
|
metaDB, err := boltdb.New(boltDriver, log.NewLogger("debug", ""))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
// Refactor Idea: We can use InitializeTestMetaDB
|
||||||
|
|
||||||
// Create metadb data for scannable image with vulnerabilities
|
// Create metadb data for scannable image with vulnerabilities
|
||||||
image11 := CreateImageWith().DefaultLayers().
|
image11 := CreateImageWith().DefaultLayers().
|
||||||
ImageConfig(ispec.Image{Created: DateRef(2008, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
ImageConfig(ispec.Image{Created: DateRef(2008, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
||||||
|
|
||||||
repoMeta11 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference("repo1", "0.1.0", image11.AsImageMeta())
|
||||||
ManifestBlob: image11.ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: image11.ConfigDescriptor.Data,
|
|
||||||
DownloadCount: 0,
|
|
||||||
Signatures: mTypes.ManifestSignatures{},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetManifestMeta("repo1", image11.ManifestDescriptor.Digest, repoMeta11)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference("repo1", "0.1.0", image11.ManifestDescriptor.Digest, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
image12 := CreateImageWith().DefaultLayers().
|
image12 := CreateImageWith().DefaultLayers().
|
||||||
ImageConfig(ispec.Image{Created: DateRef(2009, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
ImageConfig(ispec.Image{Created: DateRef(2009, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
||||||
|
|
||||||
repoMeta12 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference("repo1", "1.0.0", image12.AsImageMeta())
|
||||||
ManifestBlob: image12.ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: image12.ConfigDescriptor.Data,
|
|
||||||
DownloadCount: 0,
|
|
||||||
Signatures: mTypes.ManifestSignatures{},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetManifestMeta("repo1", image12.ManifestDescriptor.Digest, repoMeta12)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference("repo1", "1.0.0", image12.ManifestDescriptor.Digest, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
image13 := CreateImageWith().DefaultLayers().
|
image13 := CreateImageWith().DefaultLayers().
|
||||||
ImageConfig(ispec.Image{Created: DateRef(2010, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
ImageConfig(ispec.Image{Created: DateRef(2010, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
||||||
|
|
||||||
repoMeta13 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference("repo1", "1.1.0", image13.AsImageMeta())
|
||||||
ManifestBlob: image13.ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: image13.ConfigDescriptor.Data,
|
|
||||||
DownloadCount: 0,
|
|
||||||
Signatures: mTypes.ManifestSignatures{},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetManifestMeta("repo1", image13.ManifestDescriptor.Digest, repoMeta13)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference("repo1", "1.1.0", image13.ManifestDescriptor.Digest, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
image14 := CreateImageWith().DefaultLayers().
|
image14 := CreateImageWith().DefaultLayers().
|
||||||
ImageConfig(ispec.Image{Created: DateRef(2011, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
ImageConfig(ispec.Image{Created: DateRef(2011, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
||||||
|
|
||||||
repoMeta14 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference("repo1", "1.0.1", image14.AsImageMeta())
|
||||||
ManifestBlob: image14.ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: image14.ConfigDescriptor.Data,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetManifestMeta("repo1", image14.ManifestDescriptor.Digest, repoMeta14)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference("repo1", "1.0.1", image14.ManifestDescriptor.Digest, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// Create metadb data for scannable image with no vulnerabilities
|
// Create metadb data for scannable image with no vulnerabilities
|
||||||
image61 := CreateImageWith().DefaultLayers().
|
image61 := CreateImageWith().DefaultLayers().
|
||||||
ImageConfig(ispec.Image{Created: DateRef(2016, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
ImageConfig(ispec.Image{Created: DateRef(2016, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
||||||
|
|
||||||
repoMeta61 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference("repo6", "1.0.0", image61.AsImageMeta())
|
||||||
ManifestBlob: image61.ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: image61.ConfigDescriptor.Data,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetManifestMeta("repo6", image61.ManifestDescriptor.Digest, repoMeta61)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference("repo6", "1.0.0", image61.ManifestDescriptor.Digest, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// Create metadb data for image not supporting scanning
|
// Create metadb data for image not supporting scanning
|
||||||
@ -149,104 +109,58 @@ func TestScanGeneratorWithMockedData(t *testing.T) { //nolint: gocyclo
|
|||||||
Digest: godigest.FromBytes([]byte{10, 10, 10}),
|
Digest: godigest.FromBytes([]byte{10, 10, 10}),
|
||||||
}}).ImageConfig(ispec.Image{Created: DateRef(2009, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
}}).ImageConfig(ispec.Image{Created: DateRef(2009, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
||||||
|
|
||||||
repoMeta21 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference("repo2", "1.0.0", image21.AsImageMeta())
|
||||||
ManifestBlob: image21.ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: image21.ConfigDescriptor.Data,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetManifestMeta("repo2", image21.ManifestDescriptor.Digest, repoMeta21)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference("repo2", "1.0.0", image21.ManifestDescriptor.Digest, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// Create metadb data for invalid images/negative tests
|
// Create metadb data for invalid images/negative tests
|
||||||
manifestBlob31 := []byte("invalid manifest blob")
|
img := CreateRandomImage()
|
||||||
So(err, ShouldBeNil)
|
digest31 := img.Digest()
|
||||||
|
|
||||||
repoMeta31 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference("repo3", "invalid-manifest", img.AsImageMeta())
|
||||||
ManifestBlob: manifestBlob31,
|
|
||||||
}
|
|
||||||
|
|
||||||
digest31 := godigest.FromBytes(manifestBlob31)
|
|
||||||
err = metaDB.SetManifestMeta("repo3", digest31, repoMeta31)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference("repo3", "invalid-manifest", digest31, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
image41 := CreateImageWith().DefaultLayers().
|
image41 := CreateImageWith().DefaultLayers().
|
||||||
CustomConfigBlob([]byte("invalid config blob"), ispec.MediaTypeImageConfig).Build()
|
CustomConfigBlob([]byte("invalid config blob"), ispec.MediaTypeImageConfig).Build()
|
||||||
|
|
||||||
repoMeta41 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference("repo4", "invalid-config", image41.AsImageMeta())
|
||||||
ManifestBlob: image41.ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: image41.ConfigDescriptor.Data,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetManifestMeta("repo4", image41.ManifestDescriptor.Digest, repoMeta41)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference("repo4", "invalid-config", image41.ManifestDescriptor.Digest,
|
|
||||||
ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
digest51 := godigest.FromString("abc8")
|
image15 := CreateRandomMultiarch()
|
||||||
err = metaDB.SetRepoReference("repo5", "nonexitent-manifest", digest51, ispec.MediaTypeImageManifest)
|
|
||||||
|
digest51 := image15.Digest()
|
||||||
|
err = metaDB.SetRepoReference("repo5", "nonexitent-manifests-for-multiarch", image15.AsImageMeta())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// Create metadb data for scannable image which errors during scan
|
// Create metadb data for scannable image which errors during scan
|
||||||
image71 := CreateImageWith().DefaultLayers().
|
image71 := CreateImageWith().DefaultLayers().
|
||||||
ImageConfig(ispec.Image{Created: DateRef(2000, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
ImageConfig(ispec.Image{Created: DateRef(2000, 1, 1, 12, 0, 0, 0, time.UTC)}).Build()
|
||||||
|
|
||||||
repoMeta71 := mTypes.ManifestMetadata{
|
err = metaDB.SetRepoReference("repo7", "1.0.0", image71.AsImageMeta())
|
||||||
ManifestBlob: image71.ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: image71.ConfigDescriptor.Data,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetManifestMeta("repo7", image71.ManifestDescriptor.Digest, repoMeta71)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
err = metaDB.SetRepoReference("repo7", "1.0.0", image71.ManifestDescriptor.Digest, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// Create multiarch image with vulnerabilities
|
// Create multiarch image with vulnerabilities
|
||||||
multiarchImage := CreateRandomMultiarch()
|
multiarchImage := CreateRandomMultiarch()
|
||||||
|
|
||||||
err = metaDB.SetIndexData(
|
err = metaDB.SetRepoReference(repoIndex, multiarchImage.Images[0].DigestStr(),
|
||||||
multiarchImage.IndexDescriptor.Digest,
|
multiarchImage.Images[0].AsImageMeta())
|
||||||
mTypes.IndexData{IndexBlob: multiarchImage.IndexDescriptor.Data},
|
So(err, ShouldBeNil)
|
||||||
)
|
err = metaDB.SetRepoReference(repoIndex, multiarchImage.Images[1].DigestStr(),
|
||||||
|
multiarchImage.Images[1].AsImageMeta())
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
err = metaDB.SetRepoReference(repoIndex, multiarchImage.Images[2].DigestStr(),
|
||||||
|
multiarchImage.Images[2].AsImageMeta())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
err = metaDB.SetManifestData(
|
err = metaDB.SetRepoReference(repoIndex, "tagIndex", multiarchImage.AsImageMeta())
|
||||||
multiarchImage.Images[0].ManifestDescriptor.Digest,
|
So(err, ShouldBeNil)
|
||||||
mTypes.ManifestData{
|
|
||||||
ManifestBlob: multiarchImage.Images[0].ManifestDescriptor.Data,
|
err = metaDB.SetRepoMeta("repo-with-bad-tag-digest", mTypes.RepoMeta{
|
||||||
ConfigBlob: multiarchImage.Images[0].ConfigDescriptor.Data,
|
Name: "repo-with-bad-tag-digest",
|
||||||
|
Tags: map[string]mTypes.Descriptor{
|
||||||
|
"tag": {MediaType: ispec.MediaTypeImageManifest, Digest: godigest.FromString("1").String()},
|
||||||
|
"tag-multi-arch": {MediaType: ispec.MediaTypeImageIndex, Digest: godigest.FromString("2").String()},
|
||||||
},
|
},
|
||||||
)
|
})
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = metaDB.SetManifestData(
|
|
||||||
multiarchImage.Images[1].ManifestDescriptor.Digest,
|
|
||||||
mTypes.ManifestData{
|
|
||||||
ManifestBlob: multiarchImage.Images[1].ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: multiarchImage.Images[1].ConfigDescriptor.Data,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = metaDB.SetManifestData(
|
|
||||||
multiarchImage.Images[2].ManifestDescriptor.Digest,
|
|
||||||
mTypes.ManifestData{
|
|
||||||
ManifestBlob: multiarchImage.Images[2].ManifestDescriptor.Data,
|
|
||||||
ConfigBlob: multiarchImage.Images[2].ConfigDescriptor.Data,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = metaDB.SetRepoReference(
|
|
||||||
repoIndex,
|
|
||||||
"tagIndex",
|
|
||||||
multiarchImage.IndexDescriptor.Digest,
|
|
||||||
ispec.MediaTypeImageIndex,
|
|
||||||
)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
// Keep a record of all the image references / digest pairings
|
// Keep a record of all the image references / digest pairings
|
||||||
@ -274,7 +188,7 @@ func TestScanGeneratorWithMockedData(t *testing.T) { //nolint: gocyclo
|
|||||||
image41Digest := image41.ManifestDescriptor.Digest.String()
|
image41Digest := image41.ManifestDescriptor.Digest.String()
|
||||||
image41Name := "repo4:invalid-config"
|
image41Name := "repo4:invalid-config"
|
||||||
imageMap[image41Name] = image41Digest
|
imageMap[image41Name] = image41Digest
|
||||||
image51Name := "repo5:nonexitent-manifest"
|
image51Name := "repo5:nonexitent-manifest-for-multiarch"
|
||||||
imageMap[image51Name] = digest51.String()
|
imageMap[image51Name] = digest51.String()
|
||||||
image61Digest := image61.ManifestDescriptor.Digest.String()
|
image61Digest := image61.ManifestDescriptor.Digest.String()
|
||||||
image61Name := "repo6:1.0.0"
|
image61Name := "repo6:1.0.0"
|
||||||
@ -296,7 +210,7 @@ func TestScanGeneratorWithMockedData(t *testing.T) { //nolint: gocyclo
|
|||||||
imageMap[indexM3Name] = indexM3Digest
|
imageMap[indexM3Name] = indexM3Digest
|
||||||
|
|
||||||
// Initialize a test CVE cache
|
// Initialize a test CVE cache
|
||||||
cache := cvecache.NewCveCache(10, logger)
|
cache := cvecache.NewCveCache(20, logger)
|
||||||
|
|
||||||
// MetaDB loaded with initial data, now mock the scanner
|
// MetaDB loaded with initial data, now mock the scanner
|
||||||
// Setup test CVE data in mock scanner
|
// Setup test CVE data in mock scanner
|
||||||
@ -440,7 +354,7 @@ func TestScanGeneratorWithMockedData(t *testing.T) { //nolint: gocyclo
|
|||||||
// Almost same logic compared to actual Trivy specific implementation
|
// Almost same logic compared to actual Trivy specific implementation
|
||||||
imageDir, inputTag := repo, reference
|
imageDir, inputTag := repo, reference
|
||||||
|
|
||||||
repoMeta, err := metaDB.GetRepoMeta(imageDir)
|
repoMeta, err := metaDB.GetRepoMeta(context.Background(), imageDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@ -463,19 +377,12 @@ func TestScanGeneratorWithMockedData(t *testing.T) { //nolint: gocyclo
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
manifestData, err := metaDB.GetManifestData(manifestDigest)
|
manifestData, err := metaDB.GetImageMeta(manifestDigest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var manifestContent ispec.Manifest
|
for _, imageLayer := range manifestData.Manifests[0].Manifest.Layers {
|
||||||
|
|
||||||
err = json.Unmarshal(manifestData.ManifestBlob, &manifestContent)
|
|
||||||
if err != nil {
|
|
||||||
return false, zerr.ErrScanNotSupported
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, imageLayer := range manifestContent.Layers {
|
|
||||||
switch imageLayer.MediaType {
|
switch imageLayer.MediaType {
|
||||||
case ispec.MediaTypeImageLayerGzip, ispec.MediaTypeImageLayer, string(regTypes.DockerLayer):
|
case ispec.MediaTypeImageLayerGzip, ispec.MediaTypeImageLayer, string(regTypes.DockerLayer):
|
||||||
|
|
||||||
@ -531,7 +438,7 @@ func TestScanGeneratorWithMockedData(t *testing.T) { //nolint: gocyclo
|
|||||||
|
|
||||||
// Make sure the scanner generator has completed despite errors
|
// Make sure the scanner generator has completed despite errors
|
||||||
found, err := test.ReadLogFileAndSearchString(logPath,
|
found, err := test.ReadLogFileAndSearchString(logPath,
|
||||||
"Scheduled CVE scan: finished for available images", 20*time.Second)
|
"Scheduled CVE scan: finished for available images", 40*time.Second)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(found, ShouldBeTrue)
|
So(found, ShouldBeTrue)
|
||||||
|
|
||||||
@ -546,13 +453,12 @@ func TestScanGeneratorWithMockedData(t *testing.T) { //nolint: gocyclo
|
|||||||
t.Log("expecting " + image + " " + digestStr + " to be present in cache")
|
t.Log("expecting " + image + " " + digestStr + " to be present in cache")
|
||||||
So(scanner.IsResultCached(digestStr), ShouldBeTrue)
|
So(scanner.IsResultCached(digestStr), ShouldBeTrue)
|
||||||
} else {
|
} else {
|
||||||
// We don't cache results for unscannable manifests
|
// We don't cache results for un-scannable manifests
|
||||||
t.Log("expecting " + image + " " + digestStr + " to be absent from cache")
|
t.Log("expecting " + image + " " + digestStr + " to be absent from cache")
|
||||||
So(scanner.IsResultCached(digestStr), ShouldBeFalse)
|
So(scanner.IsResultCached(digestStr), ShouldBeFalse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the scanner generator is catching the metadb error for repo5:nonexitent-manifest
|
|
||||||
found, err = test.ReadLogFileAndSearchString(logPath,
|
found, err = test.ReadLogFileAndSearchString(logPath,
|
||||||
"Scheduled CVE scan: error while obtaining repo metadata", 20*time.Second)
|
"Scheduled CVE scan: error while obtaining repo metadata", 20*time.Second)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
@ -2,7 +2,6 @@ package trivy
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@ -26,7 +25,6 @@ import (
|
|||||||
cvecache "zotregistry.io/zot/pkg/extensions/search/cve/cache"
|
cvecache "zotregistry.io/zot/pkg/extensions/search/cve/cache"
|
||||||
cvemodel "zotregistry.io/zot/pkg/extensions/search/cve/model"
|
cvemodel "zotregistry.io/zot/pkg/extensions/search/cve/model"
|
||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
mcommon "zotregistry.io/zot/pkg/meta/common"
|
|
||||||
mTypes "zotregistry.io/zot/pkg/meta/types"
|
mTypes "zotregistry.io/zot/pkg/meta/types"
|
||||||
"zotregistry.io/zot/pkg/storage"
|
"zotregistry.io/zot/pkg/storage"
|
||||||
)
|
)
|
||||||
@ -193,7 +191,7 @@ func (scanner Scanner) IsImageFormatScannable(repo, ref string) (bool, error) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if zcommon.IsTag(ref) {
|
if zcommon.IsTag(ref) {
|
||||||
imgDescriptor, err := mcommon.GetImageDescriptor(scanner.metaDB, repo, ref)
|
imgDescriptor, err := getImageDescriptor(scanner.metaDB, repo, ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@ -203,7 +201,7 @@ func (scanner Scanner) IsImageFormatScannable(repo, ref string) (bool, error) {
|
|||||||
} else {
|
} else {
|
||||||
var found bool
|
var found bool
|
||||||
|
|
||||||
found, mediaType = mcommon.FindMediaTypeForDigest(scanner.metaDB, godigest.Digest(ref))
|
found, mediaType = findMediaTypeForDigest(scanner.metaDB, godigest.Digest(ref))
|
||||||
if !found {
|
if !found {
|
||||||
return false, zerr.ErrManifestNotFound
|
return false, zerr.ErrManifestNotFound
|
||||||
}
|
}
|
||||||
@ -224,7 +222,7 @@ func (scanner Scanner) IsImageMediaScannable(repo, digestStr, mediaType string)
|
|||||||
|
|
||||||
return ok, nil
|
return ok, nil
|
||||||
case ispec.MediaTypeImageIndex:
|
case ispec.MediaTypeImageIndex:
|
||||||
ok, err := scanner.isIndexScanable(digestStr)
|
ok, err := scanner.isIndexScannable(digestStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ok, fmt.Errorf("image '%s' %w", image, err)
|
return ok, fmt.Errorf("image '%s' %w", image, err)
|
||||||
}
|
}
|
||||||
@ -240,21 +238,16 @@ func (scanner Scanner) isManifestScanable(digestStr string) (bool, error) {
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
manifestData, err := scanner.metaDB.GetManifestData(godigest.Digest(digestStr))
|
manifestData, err := scanner.metaDB.GetImageMeta(godigest.Digest(digestStr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var manifestContent ispec.Manifest
|
if manifestData.MediaType != ispec.MediaTypeImageManifest {
|
||||||
|
return false, zerr.ErrUnexpectedMediaType
|
||||||
err = json.Unmarshal(manifestData.ManifestBlob, &manifestContent)
|
|
||||||
if err != nil {
|
|
||||||
scanner.log.Error().Err(err).Msg("unable to unmashal manifest blob")
|
|
||||||
|
|
||||||
return false, zerr.ErrScanNotSupported
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, imageLayer := range manifestContent.Layers {
|
for _, imageLayer := range manifestData.Manifests[0].Manifest.Layers {
|
||||||
switch imageLayer.MediaType {
|
switch imageLayer.MediaType {
|
||||||
case ispec.MediaTypeImageLayerGzip, ispec.MediaTypeImageLayer, string(regTypes.DockerLayer):
|
case ispec.MediaTypeImageLayerGzip, ispec.MediaTypeImageLayer, string(regTypes.DockerLayer):
|
||||||
continue
|
continue
|
||||||
@ -266,34 +259,54 @@ func (scanner Scanner) isManifestScanable(digestStr string) (bool, error) {
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scanner Scanner) isIndexScanable(digestStr string) (bool, error) {
|
func (scanner Scanner) isManifestDataScannable(manifestData mTypes.ManifestData) (bool, error) {
|
||||||
|
if scanner.cache.Get(manifestData.Digest.String()) != nil {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if manifestData.Manifest.MediaType != ispec.MediaTypeImageManifest {
|
||||||
|
return false, zerr.ErrScanNotSupported
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, imageLayer := range manifestData.Manifest.Layers {
|
||||||
|
switch imageLayer.MediaType {
|
||||||
|
case ispec.MediaTypeImageLayerGzip, ispec.MediaTypeImageLayer, string(regTypes.DockerLayer):
|
||||||
|
continue
|
||||||
|
default:
|
||||||
|
return false, zerr.ErrScanNotSupported
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (scanner Scanner) isIndexScannable(digestStr string) (bool, error) {
|
||||||
if scanner.cache.Get(digestStr) != nil {
|
if scanner.cache.Get(digestStr) != nil {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
indexData, err := scanner.metaDB.GetIndexData(godigest.Digest(digestStr))
|
indexData, err := scanner.metaDB.GetImageMeta(godigest.Digest(digestStr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var indexContent ispec.Index
|
if indexData.MediaType != ispec.MediaTypeImageIndex || indexData.Index == nil {
|
||||||
|
return false, zerr.ErrUnexpectedMediaType
|
||||||
err = json.Unmarshal(indexData.IndexBlob, &indexContent)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
indexContent := *indexData.Index
|
||||||
|
|
||||||
if len(indexContent.Manifests) == 0 {
|
if len(indexContent.Manifests) == 0 {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, manifest := range indexContent.Manifests {
|
for _, manifest := range indexData.Manifests {
|
||||||
isScannable, err := scanner.isManifestScanable(manifest.Digest.String())
|
isScannable, err := scanner.isManifestDataScannable(manifest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// if at least 1 manifest is scanable, the whole index is scanable
|
// if at least 1 manifest is scannable, the whole index is scannable
|
||||||
if isScannable {
|
if isScannable {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
@ -323,7 +336,7 @@ func (scanner Scanner) ScanImage(image string) (map[string]cvemodel.CVE, error)
|
|||||||
digest = ref
|
digest = ref
|
||||||
|
|
||||||
if isTag {
|
if isTag {
|
||||||
imgDescriptor, err := mcommon.GetImageDescriptor(scanner.metaDB, repo, ref)
|
imgDescriptor, err := getImageDescriptor(scanner.metaDB, repo, ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return map[string]cvemodel.CVE{}, err
|
return map[string]cvemodel.CVE{}, err
|
||||||
}
|
}
|
||||||
@ -333,7 +346,7 @@ func (scanner Scanner) ScanImage(image string) (map[string]cvemodel.CVE, error)
|
|||||||
} else {
|
} else {
|
||||||
var found bool
|
var found bool
|
||||||
|
|
||||||
found, mediaType = mcommon.FindMediaTypeForDigest(scanner.metaDB, godigest.Digest(ref))
|
found, mediaType = findMediaTypeForDigest(scanner.metaDB, godigest.Digest(ref))
|
||||||
if !found {
|
if !found {
|
||||||
return map[string]cvemodel.CVE{}, zerr.ErrManifestNotFound
|
return map[string]cvemodel.CVE{}, zerr.ErrManifestNotFound
|
||||||
}
|
}
|
||||||
@ -441,21 +454,18 @@ func (scanner Scanner) scanIndex(repo, digest string) (map[string]cvemodel.CVE,
|
|||||||
return cachedMap, nil
|
return cachedMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
indexData, err := scanner.metaDB.GetIndexData(godigest.Digest(digest))
|
indexData, err := scanner.metaDB.GetImageMeta(godigest.Digest(digest))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return map[string]cvemodel.CVE{}, err
|
return map[string]cvemodel.CVE{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var indexContent ispec.Index
|
if indexData.Index == nil {
|
||||||
|
return map[string]cvemodel.CVE{}, zerr.ErrUnexpectedMediaType
|
||||||
err = json.Unmarshal(indexData.IndexBlob, &indexContent)
|
|
||||||
if err != nil {
|
|
||||||
return map[string]cvemodel.CVE{}, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
indexCveIDMap := map[string]cvemodel.CVE{}
|
indexCveIDMap := map[string]cvemodel.CVE{}
|
||||||
|
|
||||||
for _, manifest := range indexContent.Manifests {
|
for _, manifest := range indexData.Index.Manifests {
|
||||||
if isScannable, err := scanner.isManifestScanable(manifest.Digest.String()); isScannable && err == nil {
|
if isScannable, err := scanner.isManifestScanable(manifest.Digest.String()); isScannable && err == nil {
|
||||||
manifestCveIDMap, err := scanner.scanManifest(repo, manifest.Digest.String())
|
manifestCveIDMap, err := scanner.scanManifest(repo, manifest.Digest.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -567,6 +577,31 @@ func (scanner Scanner) checkDBPresence() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getImageDescriptor(metaDB mTypes.MetaDB, repo, tag string) (mTypes.Descriptor, error) {
|
||||||
|
repoMeta, err := metaDB.GetRepoMeta(context.Background(), repo)
|
||||||
|
if err != nil {
|
||||||
|
return mTypes.Descriptor{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
imageDescriptor, ok := repoMeta.Tags[tag]
|
||||||
|
if !ok {
|
||||||
|
return mTypes.Descriptor{}, zerr.ErrTagMetaNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
return imageDescriptor, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// findMediaTypeForDigest will look into the buckets for a certain digest. Depending on which bucket that
|
||||||
|
// digest is found the corresponding mediatype is returned.
|
||||||
|
func findMediaTypeForDigest(metaDB mTypes.MetaDB, digest godigest.Digest) (bool, string) {
|
||||||
|
imageMeta, err := metaDB.GetImageMeta(digest)
|
||||||
|
if err == nil {
|
||||||
|
return true, imageMeta.MediaType
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
|
|
||||||
func convertSeverity(detectedSeverity string) string {
|
func convertSeverity(detectedSeverity string) string {
|
||||||
trivySeverity, _ := dbTypes.NewSeverity(detectedSeverity)
|
trivySeverity, _ := dbTypes.NewSeverity(detectedSeverity)
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ import (
|
|||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
"zotregistry.io/zot/pkg/meta"
|
"zotregistry.io/zot/pkg/meta"
|
||||||
"zotregistry.io/zot/pkg/meta/boltdb"
|
"zotregistry.io/zot/pkg/meta/boltdb"
|
||||||
mTypes "zotregistry.io/zot/pkg/meta/types"
|
"zotregistry.io/zot/pkg/meta/types"
|
||||||
"zotregistry.io/zot/pkg/storage"
|
"zotregistry.io/zot/pkg/storage"
|
||||||
"zotregistry.io/zot/pkg/storage/imagestore"
|
"zotregistry.io/zot/pkg/storage/imagestore"
|
||||||
"zotregistry.io/zot/pkg/storage/local"
|
"zotregistry.io/zot/pkg/storage/local"
|
||||||
@ -288,114 +288,31 @@ func TestImageScannable(t *testing.T) {
|
|||||||
// Create metadb data for scannable image
|
// Create metadb data for scannable image
|
||||||
timeStamp := time.Date(2008, 1, 1, 12, 0, 0, 0, time.UTC)
|
timeStamp := time.Date(2008, 1, 1, 12, 0, 0, 0, time.UTC)
|
||||||
|
|
||||||
validConfigBlob, err := json.Marshal(ispec.Image{
|
validConfig := ispec.Image{
|
||||||
Created: &timeStamp,
|
Created: &timeStamp,
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
validManifestBlob, err := json.Marshal(ispec.Manifest{
|
validImage := CreateImageWith().
|
||||||
Config: ispec.Descriptor{
|
Layers([]Layer{{
|
||||||
MediaType: ispec.MediaTypeImageConfig,
|
|
||||||
Size: 0,
|
|
||||||
Digest: godigest.FromBytes(validConfigBlob),
|
|
||||||
},
|
|
||||||
Layers: []ispec.Descriptor{
|
|
||||||
{
|
|
||||||
MediaType: ispec.MediaTypeImageLayerGzip,
|
MediaType: ispec.MediaTypeImageLayerGzip,
|
||||||
Size: 0,
|
Digest: ispec.DescriptorEmptyJSON.Digest,
|
||||||
Digest: godigest.NewDigestFromEncoded(godigest.SHA256, "digest"),
|
Blob: ispec.DescriptorEmptyJSON.Data,
|
||||||
},
|
}}).ImageConfig(validConfig).Build()
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
validRepoMeta := mTypes.ManifestData{
|
err = metaDB.SetRepoReference("repo1", "valid", validImage.AsImageMeta())
|
||||||
ManifestBlob: validManifestBlob,
|
|
||||||
ConfigBlob: validConfigBlob,
|
|
||||||
}
|
|
||||||
|
|
||||||
digestValidManifest := godigest.FromBytes(validManifestBlob)
|
|
||||||
|
|
||||||
err = metaDB.SetManifestData(digestValidManifest, validRepoMeta)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetRepoReference("repo1", "valid", digestValidManifest, ispec.MediaTypeImageManifest)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create MetaDB data for manifest with unscannable layers
|
// Create MetaDB data for manifest with unscannable layers
|
||||||
manifestBlobUnscannableLayer, err := json.Marshal(ispec.Manifest{
|
imageWithUnscannableLayer := CreateImageWith().
|
||||||
Config: ispec.Descriptor{
|
Layers([]Layer{{
|
||||||
MediaType: ispec.MediaTypeImageConfig,
|
|
||||||
Size: 0,
|
|
||||||
Digest: godigest.FromBytes(validConfigBlob),
|
|
||||||
},
|
|
||||||
Layers: []ispec.Descriptor{
|
|
||||||
{
|
|
||||||
MediaType: "unscannable_media_type",
|
MediaType: "unscannable_media_type",
|
||||||
Size: 0,
|
Digest: ispec.DescriptorEmptyJSON.Digest,
|
||||||
Digest: godigest.NewDigestFromEncoded(godigest.SHA256, "digest"),
|
Blob: ispec.DescriptorEmptyJSON.Data,
|
||||||
},
|
}}).ImageConfig(validConfig).Build()
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
repoMetaUnscannableLayer := mTypes.ManifestData{
|
err = metaDB.SetRepoReference("repo1", "unscannable-layer", imageWithUnscannableLayer.AsImageMeta())
|
||||||
ManifestBlob: manifestBlobUnscannableLayer,
|
|
||||||
ConfigBlob: validConfigBlob,
|
|
||||||
}
|
|
||||||
|
|
||||||
digestManifestUnscannableLayer := godigest.FromBytes(manifestBlobUnscannableLayer)
|
|
||||||
|
|
||||||
err = metaDB.SetManifestData(digestManifestUnscannableLayer, repoMetaUnscannableLayer)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetRepoReference("repo1", "unscannable-layer", digestManifestUnscannableLayer,
|
|
||||||
ispec.MediaTypeImageManifest)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create MetaDB data for unmarshable manifest
|
|
||||||
unmarshableManifestBlob := []byte("Some string")
|
|
||||||
repoMetaUnmarshable := mTypes.ManifestData{
|
|
||||||
ManifestBlob: unmarshableManifestBlob,
|
|
||||||
ConfigBlob: validConfigBlob,
|
|
||||||
}
|
|
||||||
|
|
||||||
digestUnmarshableManifest := godigest.FromBytes(unmarshableManifestBlob)
|
|
||||||
|
|
||||||
err = metaDB.SetManifestData(digestUnmarshableManifest, repoMetaUnmarshable)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetRepoReference("repo1", "unmarshable", digestUnmarshableManifest, ispec.MediaTypeImageManifest)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Manifest meta cannot be found
|
|
||||||
digestMissingManifest := godigest.FromBytes([]byte("Some other string"))
|
|
||||||
|
|
||||||
err = metaDB.SetRepoReference("repo1", "missing", digestMissingManifest, ispec.MediaTypeImageManifest)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RepoMeta contains invalid digest
|
|
||||||
err = metaDB.SetRepoReference("repo1", "invalid-digest", "invalid", ispec.MediaTypeImageManifest)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -423,18 +340,6 @@ func TestImageScannable(t *testing.T) {
|
|||||||
So(result, ShouldBeFalse)
|
So(result, ShouldBeFalse)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("Image with unmarshable manifests should be unscannable", t, func() {
|
|
||||||
result, err := scanner.IsImageFormatScannable("repo1", "unmarshable")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
So(result, ShouldBeFalse)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Image with missing manifest meta should be unscannable", t, func() {
|
|
||||||
result, err := scanner.IsImageFormatScannable("repo1", "missing")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
So(result, ShouldBeFalse)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Image with invalid manifest digest should be unscannable", t, func() {
|
Convey("Image with invalid manifest digest should be unscannable", t, func() {
|
||||||
result, err := scanner.IsImageFormatScannable("repo1", "invalid-digest")
|
result, err := scanner.IsImageFormatScannable("repo1", "invalid-digest")
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
@ -523,14 +428,14 @@ func TestIsIndexScanable(t *testing.T) {
|
|||||||
|
|
||||||
scanner.cache.Add("digest", make(map[string]model.CVE))
|
scanner.cache.Add("digest", make(map[string]model.CVE))
|
||||||
|
|
||||||
found, err := scanner.isIndexScanable("digest")
|
found, err := scanner.isIndexScannable("digest")
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(found, ShouldBeTrue)
|
So(found, ShouldBeTrue)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestScanIndexErrors(t *testing.T) {
|
func TestIsIndexScannableErrors(t *testing.T) {
|
||||||
Convey("Errors", t, func() {
|
Convey("Errors", t, func() {
|
||||||
storeController := storage.StoreController{}
|
storeController := storage.StoreController{}
|
||||||
storeController.DefaultStore = mocks.MockedImageStore{}
|
storeController.DefaultStore = mocks.MockedImageStore{}
|
||||||
@ -538,107 +443,22 @@ func TestScanIndexErrors(t *testing.T) {
|
|||||||
metaDB := mocks.MetaDBMock{}
|
metaDB := mocks.MetaDBMock{}
|
||||||
log := log.NewLogger("debug", "")
|
log := log.NewLogger("debug", "")
|
||||||
|
|
||||||
Convey("GetIndexData fails", func() {
|
Convey("all manifests of a index are not scannable", func() {
|
||||||
metaDB.GetIndexDataFn = func(indexDigest godigest.Digest) (mTypes.IndexData, error) {
|
unscannableLayer := []Layer{{MediaType: "unscannable-layer-type", Digest: godigest.FromString("123")}}
|
||||||
return mTypes.IndexData{}, godigest.ErrDigestUnsupported
|
img1 := CreateImageWith().Layers(unscannableLayer).RandomConfig().Build()
|
||||||
|
img2 := CreateImageWith().Layers(unscannableLayer).RandomConfig().Build()
|
||||||
|
multiarch := CreateMultiarchWith().Images([]Image{img1, img2}).Build()
|
||||||
|
|
||||||
|
metaDB.GetImageMetaFn = func(digest godigest.Digest) (types.ImageMeta, error) {
|
||||||
|
return map[string]types.ImageMeta{
|
||||||
|
img1.DigestStr(): img1.AsImageMeta(),
|
||||||
|
img2.DigestStr(): img2.AsImageMeta(),
|
||||||
|
multiarch.DigestStr(): multiarch.AsImageMeta(),
|
||||||
|
}[digest.String()], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
scanner := NewScanner(storeController, metaDB, "", "", log)
|
scanner := NewScanner(storeController, metaDB, "", "", log)
|
||||||
|
ok, err := scanner.isIndexScannable(multiarch.DigestStr())
|
||||||
_, err := scanner.scanIndex("repo", "digest")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Bad Index Blob, Unamrshal fails", func() {
|
|
||||||
metaDB.GetIndexDataFn = func(indexDigest godigest.Digest) (mTypes.IndexData, error) {
|
|
||||||
return mTypes.IndexData{
|
|
||||||
IndexBlob: []byte(`bad-blob`),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
scanner := NewScanner(storeController, metaDB, "", "", log)
|
|
||||||
|
|
||||||
_, err := scanner.scanIndex("repo", "digest")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIsIndexScanableErrors(t *testing.T) {
|
|
||||||
Convey("Errors", t, func() {
|
|
||||||
storeController := storage.StoreController{}
|
|
||||||
storeController.DefaultStore = mocks.MockedImageStore{}
|
|
||||||
|
|
||||||
metaDB := mocks.MetaDBMock{}
|
|
||||||
log := log.NewLogger("debug", "")
|
|
||||||
|
|
||||||
Convey("GetIndexData errors", func() {
|
|
||||||
metaDB.GetIndexDataFn = func(indexDigest godigest.Digest) (mTypes.IndexData, error) {
|
|
||||||
return mTypes.IndexData{}, zerr.ErrManifestDataNotFound
|
|
||||||
}
|
|
||||||
scanner := NewScanner(storeController, metaDB, "", "", log)
|
|
||||||
|
|
||||||
_, err := scanner.isIndexScanable("digest")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("bad index data, can't unmarshal", func() {
|
|
||||||
metaDB.GetIndexDataFn = func(indexDigest godigest.Digest) (mTypes.IndexData, error) {
|
|
||||||
return mTypes.IndexData{IndexBlob: []byte(`bad`)}, nil
|
|
||||||
}
|
|
||||||
scanner := NewScanner(storeController, metaDB, "", "", log)
|
|
||||||
|
|
||||||
ok, err := scanner.isIndexScanable("digest")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
So(ok, ShouldBeFalse)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("is Manifest Scanable errors", func() {
|
|
||||||
metaDB.GetIndexDataFn = func(indexDigest godigest.Digest) (mTypes.IndexData, error) {
|
|
||||||
return mTypes.IndexData{IndexBlob: []byte(`{
|
|
||||||
"manifests": [{
|
|
||||||
"digest": "digest2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"digest": "digest1"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}`)}, nil
|
|
||||||
}
|
|
||||||
metaDB.GetManifestDataFn = func(manifestDigest godigest.Digest) (mTypes.ManifestData, error) {
|
|
||||||
switch manifestDigest {
|
|
||||||
case "digest1":
|
|
||||||
return mTypes.ManifestData{
|
|
||||||
ManifestBlob: []byte("{}"),
|
|
||||||
}, nil
|
|
||||||
case "digest2":
|
|
||||||
return mTypes.ManifestData{}, zerr.ErrBadBlob
|
|
||||||
}
|
|
||||||
|
|
||||||
return mTypes.ManifestData{}, nil
|
|
||||||
}
|
|
||||||
scanner := NewScanner(storeController, metaDB, "", "", log)
|
|
||||||
|
|
||||||
ok, err := scanner.isIndexScanable("digest")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(ok, ShouldBeTrue)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("is Manifest Scanable returns false because no manifest is scanable", func() {
|
|
||||||
metaDB.GetIndexDataFn = func(indexDigest godigest.Digest) (mTypes.IndexData, error) {
|
|
||||||
return mTypes.IndexData{IndexBlob: []byte(`{
|
|
||||||
"manifests": [{
|
|
||||||
"digest": "digest2"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}`)}, nil
|
|
||||||
}
|
|
||||||
metaDB.GetManifestDataFn = func(manifestDigest godigest.Digest) (mTypes.ManifestData, error) {
|
|
||||||
return mTypes.ManifestData{}, zerr.ErrBadBlob
|
|
||||||
}
|
|
||||||
scanner := NewScanner(storeController, metaDB, "", "", log)
|
|
||||||
|
|
||||||
ok, err := scanner.isIndexScanable("digest")
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(ok, ShouldBeFalse)
|
So(ok, ShouldBeFalse)
|
||||||
})
|
})
|
||||||
|
@ -11,7 +11,6 @@ import (
|
|||||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
|
||||||
zerr "zotregistry.io/zot/errors"
|
|
||||||
"zotregistry.io/zot/pkg/api"
|
"zotregistry.io/zot/pkg/api"
|
||||||
"zotregistry.io/zot/pkg/api/config"
|
"zotregistry.io/zot/pkg/api/config"
|
||||||
extconf "zotregistry.io/zot/pkg/extensions/config"
|
extconf "zotregistry.io/zot/pkg/extensions/config"
|
||||||
@ -20,13 +19,11 @@ import (
|
|||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
"zotregistry.io/zot/pkg/meta"
|
"zotregistry.io/zot/pkg/meta"
|
||||||
"zotregistry.io/zot/pkg/meta/boltdb"
|
"zotregistry.io/zot/pkg/meta/boltdb"
|
||||||
mTypes "zotregistry.io/zot/pkg/meta/types"
|
|
||||||
"zotregistry.io/zot/pkg/storage"
|
"zotregistry.io/zot/pkg/storage"
|
||||||
"zotregistry.io/zot/pkg/storage/local"
|
"zotregistry.io/zot/pkg/storage/local"
|
||||||
. "zotregistry.io/zot/pkg/test/common"
|
. "zotregistry.io/zot/pkg/test/common"
|
||||||
"zotregistry.io/zot/pkg/test/deprecated"
|
"zotregistry.io/zot/pkg/test/deprecated"
|
||||||
. "zotregistry.io/zot/pkg/test/image-utils"
|
. "zotregistry.io/zot/pkg/test/image-utils"
|
||||||
"zotregistry.io/zot/pkg/test/mocks"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestScanBigTestFile(t *testing.T) {
|
func TestScanBigTestFile(t *testing.T) {
|
||||||
@ -130,31 +127,6 @@ func TestScanningByDigest(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestScannerErrors(t *testing.T) {
|
|
||||||
digest := godigest.FromString("dig")
|
|
||||||
|
|
||||||
Convey("Errors", t, func() {
|
|
||||||
storeController := storage.StoreController{}
|
|
||||||
storeController.DefaultStore = mocks.MockedImageStore{}
|
|
||||||
|
|
||||||
metaDB := mocks.MetaDBMock{}
|
|
||||||
log := log.NewLogger("debug", "")
|
|
||||||
|
|
||||||
Convey("IsImageFormatSanable", func() {
|
|
||||||
metaDB.GetManifestDataFn = func(manifestDigest godigest.Digest) (mTypes.ManifestData, error) {
|
|
||||||
return mTypes.ManifestData{}, zerr.ErrManifestDataNotFound
|
|
||||||
}
|
|
||||||
metaDB.GetIndexDataFn = func(indexDigest godigest.Digest) (mTypes.IndexData, error) {
|
|
||||||
return mTypes.IndexData{}, zerr.ErrManifestDataNotFound
|
|
||||||
}
|
|
||||||
scanner := trivy.NewScanner(storeController, metaDB, "", "", log)
|
|
||||||
|
|
||||||
_, err := scanner.ScanImage("repo@" + digest.String())
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestVulnerableLayer(t *testing.T) {
|
func TestVulnerableLayer(t *testing.T) {
|
||||||
Convey("Vulnerable layer", t, func() {
|
Convey("Vulnerable layer", t, func() {
|
||||||
vulnerableLayer, err := GetLayerWithVulnerability()
|
vulnerableLayer, err := GetLayerWithVulnerability()
|
||||||
|
@ -40,8 +40,8 @@ func TestCVEDBGenerator(t *testing.T) {
|
|||||||
sch := scheduler.NewScheduler(cfg, logger)
|
sch := scheduler.NewScheduler(cfg, logger)
|
||||||
|
|
||||||
metaDB := &mocks.MetaDBMock{
|
metaDB := &mocks.MetaDBMock{
|
||||||
GetRepoMetaFn: func(repo string) (mTypes.RepoMetadata, error) {
|
GetRepoMetaFn: func(ctx context.Context, repo string) (mTypes.RepoMeta, error) {
|
||||||
return mTypes.RepoMetadata{
|
return mTypes.RepoMeta{
|
||||||
Tags: map[string]mTypes.Descriptor{
|
Tags: map[string]mTypes.Descriptor{
|
||||||
"tag": {MediaType: ispec.MediaTypeImageIndex},
|
"tag": {MediaType: ispec.MediaTypeImageIndex},
|
||||||
},
|
},
|
||||||
|
@ -6,13 +6,11 @@ package search
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/99designs/gqlgen/graphql"
|
|
||||||
godigest "github.com/opencontainers/go-digest"
|
godigest "github.com/opencontainers/go-digest"
|
||||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/vektah/gqlparser/v2/gqlerror"
|
"github.com/vektah/gqlparser/v2/gqlerror"
|
||||||
@ -75,18 +73,14 @@ func NewResolver(log log.Logger, storeController storage.StoreController,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func FilterByDigest(digest string) mTypes.FilterFunc {
|
func FilterByDigest(digest string) mTypes.FilterFunc {
|
||||||
return func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool {
|
// imageMeta will always contain 1 manifest
|
||||||
|
return func(repoMeta mTypes.RepoMeta, imageMeta mTypes.ImageMeta) bool {
|
||||||
lookupDigest := digest
|
lookupDigest := digest
|
||||||
contains := false
|
contains := false
|
||||||
|
|
||||||
var manifest ispec.Manifest
|
manifest := imageMeta.Manifests[0]
|
||||||
|
|
||||||
err := json.Unmarshal(manifestMeta.ManifestBlob, &manifest)
|
manifestDigest := manifest.Digest.String()
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
manifestDigest := godigest.FromBytes(manifestMeta.ManifestBlob).String()
|
|
||||||
|
|
||||||
// Check the image manifest in index.json matches the search digest
|
// Check the image manifest in index.json matches the search digest
|
||||||
// This is a blob with mediaType application/vnd.oci.image.manifest.v1+json
|
// This is a blob with mediaType application/vnd.oci.image.manifest.v1+json
|
||||||
@ -96,13 +90,13 @@ func FilterByDigest(digest string) mTypes.FilterFunc {
|
|||||||
|
|
||||||
// Check the image config matches the search digest
|
// Check the image config matches the search digest
|
||||||
// This is a blob with mediaType application/vnd.oci.image.config.v1+json
|
// This is a blob with mediaType application/vnd.oci.image.config.v1+json
|
||||||
if strings.Contains(manifest.Config.Digest.String(), lookupDigest) {
|
if strings.Contains(manifest.Manifest.Config.Digest.String(), lookupDigest) {
|
||||||
contains = true
|
contains = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if the individual layers in the oci image manifest match the digest
|
// Check to see if the individual layers in the oci image manifest match the digest
|
||||||
// These are blobs with mediaType application/vnd.oci.image.layer.v1.tar+gzip
|
// These are blobs with mediaType application/vnd.oci.image.layer.v1.tar+gzip
|
||||||
for _, layer := range manifest.Layers {
|
for _, layer := range manifest.Manifest.Layers {
|
||||||
if strings.Contains(layer.Digest.String(), lookupDigest) {
|
if strings.Contains(layer.Digest.String(), lookupDigest) {
|
||||||
contains = true
|
contains = true
|
||||||
}
|
}
|
||||||
@ -124,21 +118,20 @@ func getImageListForDigest(ctx context.Context, digest string, metaDB mTypes.Met
|
|||||||
}
|
}
|
||||||
|
|
||||||
pageInput := pagination.PageInput{
|
pageInput := pagination.PageInput{
|
||||||
Limit: safeDereferencing(requestedPage.Limit, 0),
|
Limit: deref(requestedPage.Limit, 0),
|
||||||
Offset: safeDereferencing(requestedPage.Offset, 0),
|
Offset: deref(requestedPage.Offset, 0),
|
||||||
SortBy: pagination.SortCriteria(
|
SortBy: pagination.SortCriteria(
|
||||||
safeDereferencing(requestedPage.SortBy, gql_generated.SortCriteriaRelevance),
|
deref(requestedPage.SortBy, gql_generated.SortCriteriaRelevance),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
// get all repos
|
fullImageMetaList, err := metaDB.FilterTags(ctx, mTypes.AcceptAllRepoTag, FilterByDigest(digest))
|
||||||
reposMeta, manifestMetaMap, indexDataMap, err := metaDB.FilterTags(ctx, FilterByDigest(digest))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedImagesResult{}, err
|
return &gql_generated.PaginatedImagesResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
imageSummaries, pageInfo, err := convert.PaginatedRepoMeta2ImageSummaries(ctx, reposMeta, manifestMetaMap,
|
imageSummaries, pageInfo, err := convert.PaginatedFullImageMeta2ImageSummaries(ctx, fullImageMetaList, skip,
|
||||||
indexDataMap, skip, cveInfo, mTypes.Filter{}, pageInput)
|
cveInfo, mTypes.Filter{}, pageInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedImagesResult{}, err
|
return &gql_generated.PaginatedImagesResult{}, err
|
||||||
}
|
}
|
||||||
@ -157,7 +150,7 @@ func getImageSummary(ctx context.Context, repo, tag string, digest *string, skip
|
|||||||
) (
|
) (
|
||||||
*gql_generated.ImageSummary, error,
|
*gql_generated.ImageSummary, error,
|
||||||
) {
|
) {
|
||||||
repoMeta, err := metaDB.GetRepoMeta(repo)
|
repoMeta, err := metaDB.GetRepoMeta(ctx, repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -167,108 +160,23 @@ func getImageSummary(ctx context.Context, repo, tag string, digest *string, skip
|
|||||||
return nil, gqlerror.Errorf("can't find image: %s:%s", repo, tag)
|
return nil, gqlerror.Errorf("can't find image: %s:%s", repo, tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
for t := range repoMeta.Tags {
|
repoMeta.Tags = map[string]mTypes.Descriptor{tag: manifestDescriptor}
|
||||||
if t != tag {
|
|
||||||
delete(repoMeta.Tags, t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
manifestMetaMap = map[string]mTypes.ManifestMetadata{}
|
|
||||||
indexDataMap = map[string]mTypes.IndexData{}
|
|
||||||
)
|
|
||||||
|
|
||||||
switch manifestDescriptor.MediaType {
|
|
||||||
case ispec.MediaTypeImageManifest:
|
|
||||||
manifestDigest := manifestDescriptor.Digest
|
|
||||||
|
|
||||||
if digest != nil && *digest != manifestDigest {
|
|
||||||
return nil, fmt.Errorf("resolver: can't get ManifestData for digest %s for image '%s:%s' %w",
|
|
||||||
manifestDigest, repo, tag, zerr.ErrManifestDataNotFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
manifestData, err := metaDB.GetManifestData(godigest.Digest(manifestDigest))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
manifestMetaMap[manifestDigest] = mTypes.ManifestMetadata{
|
|
||||||
ManifestBlob: manifestData.ManifestBlob,
|
|
||||||
ConfigBlob: manifestData.ConfigBlob,
|
|
||||||
}
|
|
||||||
case ispec.MediaTypeImageIndex:
|
|
||||||
indexDigest := manifestDescriptor.Digest
|
|
||||||
|
|
||||||
indexData, err := metaDB.GetIndexData(godigest.Digest(indexDigest))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var indexContent ispec.Index
|
|
||||||
|
|
||||||
err = json.Unmarshal(indexData.IndexBlob, &indexContent)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
|
imageDigest := manifestDescriptor.Digest
|
||||||
if digest != nil {
|
if digest != nil {
|
||||||
manifestDigest := *digest
|
imageDigest = *digest
|
||||||
|
|
||||||
digestFound := false
|
|
||||||
|
|
||||||
for _, manifest := range indexContent.Manifests {
|
|
||||||
if manifest.Digest.String() == manifestDigest {
|
|
||||||
digestFound = true
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !digestFound {
|
|
||||||
return nil, fmt.Errorf("resolver: can't get ManifestData for digest %s for image '%s:%s' %w",
|
|
||||||
manifestDigest, repo, tag, zerr.ErrManifestDataNotFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
manifestData, err := metaDB.GetManifestData(godigest.Digest(manifestDigest))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("resolver: can't get ManifestData for digest %s for image '%s:%s' %w",
|
|
||||||
manifestDigest, repo, tag, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
manifestMetaMap[manifestDigest] = mTypes.ManifestMetadata{
|
|
||||||
ManifestBlob: manifestData.ManifestBlob,
|
|
||||||
ConfigBlob: manifestData.ConfigBlob,
|
|
||||||
}
|
|
||||||
|
|
||||||
// We update the tag descriptor to be the manifest descriptor with digest specified in the
|
|
||||||
// 'digest' parameter. We treat it as a standalone image.
|
|
||||||
repoMeta.Tags[tag] = mTypes.Descriptor{
|
repoMeta.Tags[tag] = mTypes.Descriptor{
|
||||||
Digest: manifestDigest,
|
Digest: imageDigest,
|
||||||
MediaType: ispec.MediaTypeImageManifest,
|
MediaType: ispec.MediaTypeImageManifest,
|
||||||
}
|
}
|
||||||
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, manifest := range indexContent.Manifests {
|
imageMetaMap, err := metaDB.FilterImageMeta(ctx, []string{imageDigest})
|
||||||
manifestData, err := metaDB.GetManifestData(manifest.Digest)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("resolver: can't get ManifestData for digest %s for image '%s:%s' %w",
|
return &gql_generated.ImageSummary{}, err
|
||||||
manifest.Digest, repo, tag, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
manifestMetaMap[manifest.Digest.String()] = mTypes.ManifestMetadata{
|
imageSummaries := convert.RepoMeta2ImageSummaries(ctx, repoMeta, imageMetaMap, skipCVE, cveInfo)
|
||||||
ManifestBlob: manifestData.ManifestBlob,
|
|
||||||
ConfigBlob: manifestData.ConfigBlob,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
indexDataMap[indexDigest] = indexData
|
|
||||||
default:
|
|
||||||
log.Error().Str("mediaType", manifestDescriptor.MediaType).Msg("resolver: media type not supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
imageSummaries := convert.RepoMeta2ImageSummaries(ctx, repoMeta, manifestMetaMap, indexDataMap, skipCVE, cveInfo)
|
|
||||||
|
|
||||||
if len(imageSummaries) == 0 {
|
if len(imageSummaries) == 0 {
|
||||||
return &gql_generated.ImageSummary{}, nil
|
return &gql_generated.ImageSummary{}, nil
|
||||||
@ -290,10 +198,10 @@ func getCVEListForImage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pageInput := cvemodel.PageInput{
|
pageInput := cvemodel.PageInput{
|
||||||
Limit: safeDereferencing(requestedPage.Limit, 0),
|
Limit: deref(requestedPage.Limit, 0),
|
||||||
Offset: safeDereferencing(requestedPage.Offset, 0),
|
Offset: deref(requestedPage.Offset, 0),
|
||||||
SortBy: cvemodel.SortCriteria(
|
SortBy: cvemodel.SortCriteria(
|
||||||
safeDereferencing(requestedPage.SortBy, gql_generated.SortCriteriaSeverity),
|
deref(requestedPage.SortBy, gql_generated.SortCriteriaSeverity),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,8 +260,8 @@ func getCVEListForImage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func FilterByTagInfo(tagsInfo []cvemodel.TagInfo) mTypes.FilterFunc {
|
func FilterByTagInfo(tagsInfo []cvemodel.TagInfo) mTypes.FilterFunc {
|
||||||
return func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool {
|
return func(repoMeta mTypes.RepoMeta, imageMeta mTypes.ImageMeta) bool {
|
||||||
manifestDigest := godigest.FromBytes(manifestMeta.ManifestBlob).String()
|
manifestDigest := imageMeta.Manifests[0].Digest.String()
|
||||||
|
|
||||||
for _, tagInfo := range tagsInfo {
|
for _, tagInfo := range tagsInfo {
|
||||||
switch tagInfo.Descriptor.MediaType {
|
switch tagInfo.Descriptor.MediaType {
|
||||||
@ -375,12 +283,12 @@ func FilterByTagInfo(tagsInfo []cvemodel.TagInfo) mTypes.FilterFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func FilterByRepoAndTagInfo(repo string, tagsInfo []cvemodel.TagInfo) mTypes.FilterFunc {
|
func FilterByRepoAndTagInfo(repo string, tagsInfo []cvemodel.TagInfo) mTypes.FilterFunc {
|
||||||
return func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool {
|
return func(repoMeta mTypes.RepoMeta, imageMeta mTypes.ImageMeta) bool {
|
||||||
if repoMeta.Name != repo {
|
if repoMeta.Name != repo {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
manifestDigest := godigest.FromBytes(manifestMeta.ManifestBlob).String()
|
manifestDigest := imageMeta.Manifests[0].Digest.String()
|
||||||
|
|
||||||
for _, tagInfo := range tagsInfo {
|
for _, tagInfo := range tagsInfo {
|
||||||
switch tagInfo.Descriptor.MediaType {
|
switch tagInfo.Descriptor.MediaType {
|
||||||
@ -414,7 +322,7 @@ func getImageListForCVE(
|
|||||||
// Infinite page to make sure we scan all repos in advance, before filtering results
|
// Infinite page to make sure we scan all repos in advance, before filtering results
|
||||||
// The CVE scan logic is called from here, not in the actual filter,
|
// The CVE scan logic is called from here, not in the actual filter,
|
||||||
// this is because we shouldn't keep the DB locked while we wait on scan results
|
// this is because we shouldn't keep the DB locked while we wait on scan results
|
||||||
reposMeta, err := metaDB.GetMultipleRepoMeta(ctx, func(repoMeta mTypes.RepoMetadata) bool { return true })
|
reposMeta, err := metaDB.GetMultipleRepoMeta(ctx, func(repoMeta mTypes.RepoMeta) bool { return true })
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedImagesResult{}, err
|
return &gql_generated.PaginatedImagesResult{}, err
|
||||||
}
|
}
|
||||||
@ -457,21 +365,21 @@ func getImageListForCVE(
|
|||||||
|
|
||||||
// Actual page requested by user
|
// Actual page requested by user
|
||||||
pageInput := pagination.PageInput{
|
pageInput := pagination.PageInput{
|
||||||
Limit: safeDereferencing(requestedPage.Limit, 0),
|
Limit: deref(requestedPage.Limit, 0),
|
||||||
Offset: safeDereferencing(requestedPage.Offset, 0),
|
Offset: deref(requestedPage.Offset, 0),
|
||||||
SortBy: pagination.SortCriteria(
|
SortBy: pagination.SortCriteria(
|
||||||
safeDereferencing(requestedPage.SortBy, gql_generated.SortCriteriaUpdateTime),
|
deref(requestedPage.SortBy, gql_generated.SortCriteriaUpdateTime),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
// get all repos
|
// get all repos
|
||||||
reposMeta, manifestMetaMap, indexDataMap, err := metaDB.FilterTags(ctx, FilterByTagInfo(affectedImages))
|
fullImageMetaList, err := metaDB.FilterTags(ctx, mTypes.AcceptAllRepoTag, FilterByTagInfo(affectedImages))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedImagesResult{}, err
|
return &gql_generated.PaginatedImagesResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
imageSummaries, pageInfo, err := convert.PaginatedRepoMeta2ImageSummaries(ctx, reposMeta, manifestMetaMap,
|
imageSummaries, pageInfo, err := convert.PaginatedFullImageMeta2ImageSummaries(ctx, fullImageMetaList,
|
||||||
indexDataMap, skip, cveInfo, localFilter, pageInput)
|
skip, cveInfo, localFilter, pageInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedImagesResult{}, err
|
return &gql_generated.PaginatedImagesResult{}, err
|
||||||
}
|
}
|
||||||
@ -530,21 +438,21 @@ func getImageListWithCVEFixed(
|
|||||||
|
|
||||||
// Actual page requested by user
|
// Actual page requested by user
|
||||||
pageInput := pagination.PageInput{
|
pageInput := pagination.PageInput{
|
||||||
Limit: safeDereferencing(requestedPage.Limit, 0),
|
Limit: deref(requestedPage.Limit, 0),
|
||||||
Offset: safeDereferencing(requestedPage.Offset, 0),
|
Offset: deref(requestedPage.Offset, 0),
|
||||||
SortBy: pagination.SortCriteria(
|
SortBy: pagination.SortCriteria(
|
||||||
safeDereferencing(requestedPage.SortBy, gql_generated.SortCriteriaUpdateTime),
|
deref(requestedPage.SortBy, gql_generated.SortCriteriaUpdateTime),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
// get all repos
|
// get all repos
|
||||||
reposMeta, manifestMetaMap, indexDataMap, err := metaDB.FilterTags(ctx, FilterByRepoAndTagInfo(repo, tagsInfo))
|
fullImageMetaList, err := metaDB.FilterTags(ctx, mTypes.AcceptAllRepoTag, FilterByRepoAndTagInfo(repo, tagsInfo))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedImagesResult{}, err
|
return &gql_generated.PaginatedImagesResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
imageSummaries, pageInfo, err := convert.PaginatedRepoMeta2ImageSummaries(ctx, reposMeta, manifestMetaMap,
|
imageSummaries, pageInfo, err := convert.PaginatedFullImageMeta2ImageSummaries(ctx, fullImageMetaList,
|
||||||
indexDataMap, skip, cveInfo, localFilter, pageInput)
|
skip, cveInfo, localFilter, pageInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedImagesResult{}, err
|
return &gql_generated.PaginatedImagesResult{}, err
|
||||||
}
|
}
|
||||||
@ -576,20 +484,25 @@ func repoListWithNewestImage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pageInput := pagination.PageInput{
|
pageInput := pagination.PageInput{
|
||||||
Limit: safeDereferencing(requestedPage.Limit, 0),
|
Limit: deref(requestedPage.Limit, 0),
|
||||||
Offset: safeDereferencing(requestedPage.Offset, 0),
|
Offset: deref(requestedPage.Offset, 0),
|
||||||
SortBy: pagination.SortCriteria(
|
SortBy: pagination.SortCriteria(
|
||||||
safeDereferencing(requestedPage.SortBy, gql_generated.SortCriteriaUpdateTime),
|
deref(requestedPage.SortBy, gql_generated.SortCriteriaUpdateTime),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
reposMeta, manifestMetaMap, indexDataMap, err := metaDB.SearchRepos(ctx, "")
|
repoMetaList, err := metaDB.SearchRepos(ctx, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedReposResult{}, err
|
return &gql_generated.PaginatedReposResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
repos, pageInfo, err := convert.PaginatedRepoMeta2RepoSummaries(ctx, reposMeta, manifestMetaMap, indexDataMap,
|
imageMetaMap, err := metaDB.FilterImageMeta(ctx, mTypes.GetLatestImageDigests(repoMetaList))
|
||||||
skip, cveInfo, mTypes.Filter{}, pageInput)
|
if err != nil {
|
||||||
|
return &gql_generated.PaginatedReposResult{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
repos, pageInfo, err := convert.PaginatedRepoMeta2RepoSummaries(ctx, repoMetaList, imageMetaMap,
|
||||||
|
mTypes.Filter{}, pageInput, cveInfo, skip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedReposResult{}, err
|
return &gql_generated.PaginatedReposResult{}, err
|
||||||
}
|
}
|
||||||
@ -611,16 +524,16 @@ func getBookmarkedRepos(
|
|||||||
requestedPage *gql_generated.PageInput,
|
requestedPage *gql_generated.PageInput,
|
||||||
metaDB mTypes.MetaDB,
|
metaDB mTypes.MetaDB,
|
||||||
) (*gql_generated.PaginatedReposResult, error) {
|
) (*gql_generated.PaginatedReposResult, error) {
|
||||||
repoNames, err := metaDB.GetBookmarkedRepos(ctx)
|
bookmarkedRepos, err := metaDB.GetBookmarkedRepos(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedReposResult{}, err
|
return &gql_generated.PaginatedReposResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
filterFn := func(repoMeta mTypes.RepoMetadata) bool {
|
filterByName := func(repo string) bool {
|
||||||
return zcommon.Contains(repoNames, repoMeta.Name)
|
return zcommon.Contains(bookmarkedRepos, repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
return getFilteredPaginatedRepos(ctx, cveInfo, filterFn, log, requestedPage, metaDB)
|
return getFilteredPaginatedRepos(ctx, cveInfo, filterByName, log, requestedPage, metaDB)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStarredRepos(
|
func getStarredRepos(
|
||||||
@ -630,13 +543,13 @@ func getStarredRepos(
|
|||||||
requestedPage *gql_generated.PageInput,
|
requestedPage *gql_generated.PageInput,
|
||||||
metaDB mTypes.MetaDB,
|
metaDB mTypes.MetaDB,
|
||||||
) (*gql_generated.PaginatedReposResult, error) {
|
) (*gql_generated.PaginatedReposResult, error) {
|
||||||
repoNames, err := metaDB.GetStarredRepos(ctx)
|
starredRepos, err := metaDB.GetStarredRepos(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedReposResult{}, err
|
return &gql_generated.PaginatedReposResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
filterFn := func(repoMeta mTypes.RepoMetadata) bool {
|
filterFn := func(repo string) bool {
|
||||||
return zcommon.Contains(repoNames, repoMeta.Name)
|
return zcommon.Contains(starredRepos, repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
return getFilteredPaginatedRepos(ctx, cveInfo, filterFn, log, requestedPage, metaDB)
|
return getFilteredPaginatedRepos(ctx, cveInfo, filterFn, log, requestedPage, metaDB)
|
||||||
@ -645,7 +558,7 @@ func getStarredRepos(
|
|||||||
func getFilteredPaginatedRepos(
|
func getFilteredPaginatedRepos(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
cveInfo cveinfo.CveInfo,
|
cveInfo cveinfo.CveInfo,
|
||||||
filterFn mTypes.FilterRepoFunc,
|
filterFn mTypes.FilterRepoNameFunc,
|
||||||
log log.Logger, //nolint:unparam // may be used by devs for debugging
|
log log.Logger, //nolint:unparam // may be used by devs for debugging
|
||||||
requestedPage *gql_generated.PageInput,
|
requestedPage *gql_generated.PageInput,
|
||||||
metaDB mTypes.MetaDB,
|
metaDB mTypes.MetaDB,
|
||||||
@ -659,20 +572,25 @@ func getFilteredPaginatedRepos(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pageInput := pagination.PageInput{
|
pageInput := pagination.PageInput{
|
||||||
Limit: safeDereferencing(requestedPage.Limit, 0),
|
Limit: deref(requestedPage.Limit, 0),
|
||||||
Offset: safeDereferencing(requestedPage.Offset, 0),
|
Offset: deref(requestedPage.Offset, 0),
|
||||||
SortBy: pagination.SortCriteria(
|
SortBy: pagination.SortCriteria(
|
||||||
safeDereferencing(requestedPage.SortBy, gql_generated.SortCriteriaUpdateTime),
|
deref(requestedPage.SortBy, gql_generated.SortCriteriaUpdateTime),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
reposMeta, manifestMetaMap, indexDataMap, err := metaDB.FilterRepos(ctx, filterFn)
|
repoMetaList, err := metaDB.FilterRepos(ctx, filterFn, mTypes.AcceptAllRepoMeta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedReposResult{}, err
|
return &gql_generated.PaginatedReposResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
repos, pageInfo, err := convert.PaginatedRepoMeta2RepoSummaries(ctx, reposMeta, manifestMetaMap, indexDataMap,
|
latestImageMeta, err := metaDB.FilterImageMeta(ctx, mTypes.GetLatestImageDigests(repoMetaList))
|
||||||
skip, cveInfo, mTypes.Filter{}, pageInput)
|
if err != nil {
|
||||||
|
return &gql_generated.PaginatedReposResult{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
repos, pageInfo, err := convert.PaginatedRepoMeta2RepoSummaries(ctx, repoMetaList, latestImageMeta,
|
||||||
|
mTypes.Filter{}, pageInput, cveInfo, skip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedReposResult{}, err
|
return &gql_generated.PaginatedReposResult{}, err
|
||||||
}
|
}
|
||||||
@ -716,22 +634,31 @@ func globalSearch(ctx context.Context, query string, metaDB mTypes.MetaDB, filte
|
|||||||
}
|
}
|
||||||
|
|
||||||
pageInput := pagination.PageInput{
|
pageInput := pagination.PageInput{
|
||||||
Limit: safeDereferencing(requestedPage.Limit, 0),
|
Limit: deref(requestedPage.Limit, 0),
|
||||||
Offset: safeDereferencing(requestedPage.Offset, 0),
|
Offset: deref(requestedPage.Offset, 0),
|
||||||
SortBy: pagination.SortCriteria(
|
SortBy: pagination.SortCriteria(
|
||||||
safeDereferencing(requestedPage.SortBy, gql_generated.SortCriteriaRelevance),
|
deref(requestedPage.SortBy, gql_generated.SortCriteriaRelevance),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
reposMeta, manifestMetaMap, indexDataMap, err := metaDB.SearchRepos(ctx, query)
|
repoMetaList, err := metaDB.SearchRepos(ctx, query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedReposResult{}, []*gql_generated.ImageSummary{}, []*gql_generated.LayerSummary{}, err
|
return &gql_generated.PaginatedReposResult{}, []*gql_generated.ImageSummary{},
|
||||||
|
[]*gql_generated.LayerSummary{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
repos, pageInfo, err := convert.PaginatedRepoMeta2RepoSummaries(ctx, reposMeta, manifestMetaMap, indexDataMap,
|
imageMetaMap, err := metaDB.FilterImageMeta(ctx, mTypes.GetLatestImageDigests(repoMetaList))
|
||||||
skip, cveInfo, localFilter, pageInput)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedReposResult{}, []*gql_generated.ImageSummary{}, []*gql_generated.LayerSummary{}, err
|
return &gql_generated.PaginatedReposResult{}, []*gql_generated.ImageSummary{},
|
||||||
|
[]*gql_generated.LayerSummary{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
repos, pageInfo, err := convert.PaginatedRepoMeta2RepoSummaries(ctx, repoMetaList, imageMetaMap, localFilter,
|
||||||
|
pageInput, cveInfo,
|
||||||
|
skip)
|
||||||
|
if err != nil {
|
||||||
|
return &gql_generated.PaginatedReposResult{}, []*gql_generated.ImageSummary{},
|
||||||
|
[]*gql_generated.LayerSummary{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
paginatedRepos.Page = &gql_generated.PageInfo{
|
paginatedRepos.Page = &gql_generated.PageInfo{
|
||||||
@ -746,20 +673,20 @@ func globalSearch(ctx context.Context, query string, metaDB mTypes.MetaDB, filte
|
|||||||
}
|
}
|
||||||
|
|
||||||
pageInput := pagination.PageInput{
|
pageInput := pagination.PageInput{
|
||||||
Limit: safeDereferencing(requestedPage.Limit, 0),
|
Limit: deref(requestedPage.Limit, 0),
|
||||||
Offset: safeDereferencing(requestedPage.Offset, 0),
|
Offset: deref(requestedPage.Offset, 0),
|
||||||
SortBy: pagination.SortCriteria(
|
SortBy: pagination.SortCriteria(
|
||||||
safeDereferencing(requestedPage.SortBy, gql_generated.SortCriteriaRelevance),
|
deref(requestedPage.SortBy, gql_generated.SortCriteriaRelevance),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
reposMeta, manifestMetaMap, indexDataMap, err := metaDB.SearchTags(ctx, query)
|
fullImageMetaList, err := metaDB.SearchTags(ctx, query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedReposResult{}, []*gql_generated.ImageSummary{}, []*gql_generated.LayerSummary{}, err
|
return &gql_generated.PaginatedReposResult{}, []*gql_generated.ImageSummary{}, []*gql_generated.LayerSummary{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
imageSummaries, pageInfo, err := convert.PaginatedRepoMeta2ImageSummaries(ctx, reposMeta, manifestMetaMap,
|
imageSummaries, pageInfo, err := convert.PaginatedFullImageMeta2ImageSummaries(ctx, fullImageMetaList, skip, cveInfo,
|
||||||
indexDataMap, skip, cveInfo, localFilter, pageInput)
|
localFilter, pageInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedReposResult{}, []*gql_generated.ImageSummary{}, []*gql_generated.LayerSummary{}, err
|
return &gql_generated.PaginatedReposResult{}, []*gql_generated.ImageSummary{}, []*gql_generated.LayerSummary{}, err
|
||||||
}
|
}
|
||||||
@ -790,10 +717,10 @@ func derivedImageList(ctx context.Context, image string, digest *string, metaDB
|
|||||||
}
|
}
|
||||||
|
|
||||||
pageInput := pagination.PageInput{
|
pageInput := pagination.PageInput{
|
||||||
Limit: safeDereferencing(requestedPage.Limit, 0),
|
Limit: deref(requestedPage.Limit, 0),
|
||||||
Offset: safeDereferencing(requestedPage.Offset, 0),
|
Offset: deref(requestedPage.Offset, 0),
|
||||||
SortBy: pagination.SortCriteria(
|
SortBy: pagination.SortCriteria(
|
||||||
safeDereferencing(requestedPage.SortBy, gql_generated.SortCriteriaUpdateTime),
|
deref(requestedPage.SortBy, gql_generated.SortCriteriaUpdateTime),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -820,13 +747,13 @@ func derivedImageList(ctx context.Context, image string, digest *string, metaDB
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we need all available tags
|
// we need all available tags
|
||||||
reposMeta, manifestMetaMap, indexDataMap, err := metaDB.FilterTags(ctx, filterDerivedImages(searchedImage))
|
fullImageMetaList, err := metaDB.FilterTags(ctx, mTypes.AcceptAllRepoTag, filterDerivedImages(searchedImage))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedImagesResult{}, err
|
return &gql_generated.PaginatedImagesResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
derivedList, pageInfo, err := convert.PaginatedRepoMeta2ImageSummaries(ctx, reposMeta, manifestMetaMap, indexDataMap,
|
derivedList, pageInfo, err := convert.PaginatedFullImageMeta2ImageSummaries(ctx, fullImageMetaList, skip, cveInfo,
|
||||||
skip, cveInfo, mTypes.Filter{}, pageInput)
|
mTypes.Filter{}, pageInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedImagesResult{}, err
|
return &gql_generated.PaginatedImagesResult{}, err
|
||||||
}
|
}
|
||||||
@ -841,25 +768,20 @@ func derivedImageList(ctx context.Context, image string, digest *string, metaDB
|
|||||||
}
|
}
|
||||||
|
|
||||||
func filterDerivedImages(image *gql_generated.ImageSummary) mTypes.FilterFunc {
|
func filterDerivedImages(image *gql_generated.ImageSummary) mTypes.FilterFunc {
|
||||||
return func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool {
|
return func(repoMeta mTypes.RepoMeta, imageMeta mTypes.ImageMeta) bool {
|
||||||
var addImageToList bool
|
var addImageToList bool
|
||||||
|
|
||||||
var imageManifest ispec.Manifest
|
imageManifest := imageMeta.Manifests[0]
|
||||||
|
|
||||||
err := json.Unmarshal(manifestMeta.ManifestBlob, &imageManifest)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range image.Manifests {
|
for i := range image.Manifests {
|
||||||
manifestDigest := godigest.FromBytes(manifestMeta.ManifestBlob).String()
|
manifestDigest := imageManifest.Digest.String()
|
||||||
if manifestDigest == *image.Manifests[i].Digest {
|
if manifestDigest == *image.Manifests[i].Digest {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
imageLayers := image.Manifests[i].Layers
|
imageLayers := image.Manifests[i].Layers
|
||||||
|
|
||||||
addImageToList = false
|
addImageToList = false
|
||||||
layers := imageManifest.Layers
|
layers := imageManifest.Manifest.Layers
|
||||||
|
|
||||||
sameLayer := 0
|
sameLayer := 0
|
||||||
|
|
||||||
@ -895,10 +817,10 @@ func baseImageList(ctx context.Context, image string, digest *string, metaDB mTy
|
|||||||
}
|
}
|
||||||
|
|
||||||
pageInput := pagination.PageInput{
|
pageInput := pagination.PageInput{
|
||||||
Limit: safeDereferencing(requestedPage.Limit, 0),
|
Limit: deref(requestedPage.Limit, 0),
|
||||||
Offset: safeDereferencing(requestedPage.Offset, 0),
|
Offset: deref(requestedPage.Offset, 0),
|
||||||
SortBy: pagination.SortCriteria(
|
SortBy: pagination.SortCriteria(
|
||||||
safeDereferencing(requestedPage.SortBy, gql_generated.SortCriteriaUpdateTime),
|
deref(requestedPage.SortBy, gql_generated.SortCriteriaUpdateTime),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -926,12 +848,12 @@ func baseImageList(ctx context.Context, image string, digest *string, metaDB mTy
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we need all available tags
|
// we need all available tags
|
||||||
reposMeta, manifestMetaMap, indexDataMap, err := metaDB.FilterTags(ctx, filterBaseImages(searchedImage))
|
fullImageMetaList, err := metaDB.FilterTags(ctx, mTypes.AcceptAllRepoTag, filterBaseImages(searchedImage))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedImagesResult{}, err
|
return &gql_generated.PaginatedImagesResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
baseList, pageInfo, err := convert.PaginatedRepoMeta2ImageSummaries(ctx, reposMeta, manifestMetaMap, indexDataMap,
|
baseList, pageInfo, err := convert.PaginatedFullImageMeta2ImageSummaries(ctx, fullImageMetaList,
|
||||||
skip, cveInfo, mTypes.Filter{}, pageInput)
|
skip, cveInfo, mTypes.Filter{}, pageInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedImagesResult{}, err
|
return &gql_generated.PaginatedImagesResult{}, err
|
||||||
@ -947,25 +869,20 @@ func baseImageList(ctx context.Context, image string, digest *string, metaDB mTy
|
|||||||
}
|
}
|
||||||
|
|
||||||
func filterBaseImages(image *gql_generated.ImageSummary) mTypes.FilterFunc {
|
func filterBaseImages(image *gql_generated.ImageSummary) mTypes.FilterFunc {
|
||||||
return func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool {
|
return func(repoMeta mTypes.RepoMeta, imageMeta mTypes.ImageMeta) bool {
|
||||||
var addImageToList bool
|
var addImageToList bool
|
||||||
|
|
||||||
var manifestContent ispec.Manifest
|
manifest := imageMeta.Manifests[0]
|
||||||
|
|
||||||
err := json.Unmarshal(manifestMeta.ManifestBlob, &manifestContent)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range image.Manifests {
|
for i := range image.Manifests {
|
||||||
manifestDigest := godigest.FromBytes(manifestMeta.ManifestBlob).String()
|
manifestDigest := manifest.Digest.String()
|
||||||
if manifestDigest == *image.Manifests[i].Digest {
|
if manifestDigest == *image.Manifests[i].Digest {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
addImageToList = true
|
addImageToList = true
|
||||||
|
|
||||||
for _, l := range manifestContent.Layers {
|
for _, l := range manifest.Manifest.Layers {
|
||||||
foundLayer := false
|
foundLayer := false
|
||||||
|
|
||||||
for _, k := range image.Manifests[i].Layers {
|
for _, k := range image.Manifests[i].Layers {
|
||||||
@ -996,7 +913,7 @@ func validateGlobalSearchInput(query string, filter *gql_generated.Filter,
|
|||||||
requestedPage *gql_generated.PageInput,
|
requestedPage *gql_generated.PageInput,
|
||||||
) error {
|
) error {
|
||||||
if len(query) > querySizeLimit {
|
if len(query) > querySizeLimit {
|
||||||
return fmt.Errorf("global-search: max string size limit exeeded for query parameter. max=%d current=%d %w",
|
return fmt.Errorf("global-search: max string size limit exceeded for query parameter. max=%d current=%d %w",
|
||||||
querySizeLimit, len(query), zerr.ErrInvalidRequestParams)
|
querySizeLimit, len(query), zerr.ErrInvalidRequestParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1020,14 +937,14 @@ func checkFilter(filter *gql_generated.Filter) error {
|
|||||||
|
|
||||||
for _, arch := range filter.Arch {
|
for _, arch := range filter.Arch {
|
||||||
if len(*arch) > querySizeLimit {
|
if len(*arch) > querySizeLimit {
|
||||||
return fmt.Errorf("global-search: max string size limit exeeded for arch parameter. max=%d current=%d %w",
|
return fmt.Errorf("global-search: max string size limit exceeded for arch parameter. max=%d current=%d %w",
|
||||||
querySizeLimit, len(*arch), zerr.ErrInvalidRequestParams)
|
querySizeLimit, len(*arch), zerr.ErrInvalidRequestParams)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, osSys := range filter.Os {
|
for _, osSys := range filter.Os {
|
||||||
if len(*osSys) > querySizeLimit {
|
if len(*osSys) > querySizeLimit {
|
||||||
return fmt.Errorf("global-search: max string size limit exeeded for os parameter. max=%d current=%d %w",
|
return fmt.Errorf("global-search: max string size limit exceeded for os parameter. max=%d current=%d %w",
|
||||||
querySizeLimit, len(*osSys), zerr.ErrInvalidRequestParams)
|
querySizeLimit, len(*osSys), zerr.ErrInvalidRequestParams)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1119,92 +1036,28 @@ func expandedRepoInfo(ctx context.Context, repo string, metaDB mTypes.MetaDB, cv
|
|||||||
return &gql_generated.RepoInfo{}, nil //nolint:nilerr // don't give details to a potential attacker
|
return &gql_generated.RepoInfo{}, nil //nolint:nilerr // don't give details to a potential attacker
|
||||||
}
|
}
|
||||||
|
|
||||||
repoMeta, err := metaDB.GetUserRepoMeta(ctx, repo)
|
repoMeta, err := metaDB.GetRepoMeta(ctx, repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Str("repository", repo).Msg("resolver: can't retrieve repoMeta for repo")
|
log.Error().Err(err).Str("repository", repo).Msg("resolver: can't retrieve repoMeta for repo")
|
||||||
|
|
||||||
return &gql_generated.RepoInfo{}, err
|
return &gql_generated.RepoInfo{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
tagsDigests := []string{}
|
||||||
manifestMetaMap = map[string]mTypes.ManifestMetadata{}
|
|
||||||
indexDataMap = map[string]mTypes.IndexData{}
|
|
||||||
)
|
|
||||||
|
|
||||||
for tag, descriptor := range repoMeta.Tags {
|
for i := range repoMeta.Tags {
|
||||||
switch descriptor.MediaType {
|
if i == "" {
|
||||||
case ispec.MediaTypeImageManifest:
|
|
||||||
digest := descriptor.Digest
|
|
||||||
|
|
||||||
if _, alreadyDownloaded := manifestMetaMap[digest]; alreadyDownloaded {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
manifestData, err := metaDB.GetManifestData(godigest.Digest(digest))
|
tagsDigests = append(tagsDigests, repoMeta.Tags[i].Digest)
|
||||||
|
}
|
||||||
|
|
||||||
|
imageMetaMap, err := metaDB.FilterImageMeta(ctx, tagsDigests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
graphql.AddError(ctx, fmt.Errorf("resolver: failed to get manifest meta for image %s:%s with manifest digest %s %w",
|
log.Error().Err(err).Str("repository", repo).Msg("resolver: can't retrieve imageMeta for repo")
|
||||||
repo, tag, digest, err))
|
|
||||||
|
|
||||||
continue
|
return &gql_generated.RepoInfo{}, err
|
||||||
}
|
|
||||||
|
|
||||||
manifestMetaMap[digest] = mTypes.ManifestMetadata{
|
|
||||||
ManifestBlob: manifestData.ManifestBlob,
|
|
||||||
ConfigBlob: manifestData.ConfigBlob,
|
|
||||||
}
|
|
||||||
case ispec.MediaTypeImageIndex:
|
|
||||||
digest := descriptor.Digest
|
|
||||||
|
|
||||||
if _, alreadyDownloaded := indexDataMap[digest]; alreadyDownloaded {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
indexData, err := metaDB.GetIndexData(godigest.Digest(digest))
|
|
||||||
if err != nil {
|
|
||||||
graphql.AddError(ctx, fmt.Errorf("resolver: failed to get manifest meta for image %s:%s with manifest digest %s %w",
|
|
||||||
repo, tag, digest, err))
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var indexContent ispec.Index
|
|
||||||
|
|
||||||
err = json.Unmarshal(indexData.IndexBlob, &indexContent)
|
|
||||||
if err != nil {
|
|
||||||
graphql.AddError(ctx, fmt.Errorf("resolver: failed to unmarshal index content for image %s:%s with digest %s %w",
|
|
||||||
repo, tag, digest, err))
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var errorOccured bool
|
|
||||||
|
|
||||||
for _, descriptor := range indexContent.Manifests {
|
|
||||||
manifestData, err := metaDB.GetManifestData(descriptor.Digest)
|
|
||||||
if err != nil {
|
|
||||||
graphql.AddError(ctx,
|
|
||||||
fmt.Errorf("resolver: failed to get manifest meta with digest '%s' for multiarch image %s:%s %w",
|
|
||||||
digest, repo, tag, err),
|
|
||||||
)
|
|
||||||
|
|
||||||
errorOccured = true
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
manifestMetaMap[descriptor.Digest.String()] = mTypes.ManifestMetadata{
|
|
||||||
ManifestBlob: manifestData.ManifestBlob,
|
|
||||||
ConfigBlob: manifestData.ConfigBlob,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if errorOccured {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
indexDataMap[digest] = indexData
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
skip := convert.SkipQGLField{
|
skip := convert.SkipQGLField{
|
||||||
@ -1212,7 +1065,7 @@ func expandedRepoInfo(ctx context.Context, repo string, metaDB mTypes.MetaDB, cv
|
|||||||
canSkipField(convert.GetPreloads(ctx), "Images.Vulnerabilities"),
|
canSkipField(convert.GetPreloads(ctx), "Images.Vulnerabilities"),
|
||||||
}
|
}
|
||||||
|
|
||||||
repoSummary, imageSummaries := convert.RepoMeta2ExpandedRepoInfo(ctx, repoMeta, manifestMetaMap, indexDataMap,
|
repoSummary, imageSummaries := convert.RepoMeta2ExpandedRepoInfo(ctx, repoMeta, imageMetaMap,
|
||||||
skip, cveInfo, log)
|
skip, cveInfo, log)
|
||||||
|
|
||||||
dateSortedImages := make(timeSlice, 0, len(imageSummaries))
|
dateSortedImages := make(timeSlice, 0, len(imageSummaries))
|
||||||
@ -1239,7 +1092,7 @@ func (p timeSlice) Swap(i, j int) {
|
|||||||
p[i], p[j] = p[j], p[i]
|
p[i], p[j] = p[j], p[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
func safeDereferencing[T any](pointer *T, defaultVal T) T {
|
func deref[T any](pointer *T, defaultVal T) T {
|
||||||
if pointer != nil {
|
if pointer != nil {
|
||||||
return *pointer
|
return *pointer
|
||||||
}
|
}
|
||||||
@ -1263,23 +1116,28 @@ func getImageList(ctx context.Context, repo string, metaDB mTypes.MetaDB, cveInf
|
|||||||
}
|
}
|
||||||
|
|
||||||
pageInput := pagination.PageInput{
|
pageInput := pagination.PageInput{
|
||||||
Limit: safeDereferencing(requestedPage.Limit, 0),
|
Limit: deref(requestedPage.Limit, 0),
|
||||||
Offset: safeDereferencing(requestedPage.Offset, 0),
|
Offset: deref(requestedPage.Offset, 0),
|
||||||
SortBy: pagination.SortCriteria(
|
SortBy: pagination.SortCriteria(
|
||||||
safeDereferencing(requestedPage.SortBy, gql_generated.SortCriteriaRelevance),
|
deref(requestedPage.SortBy, gql_generated.SortCriteriaRelevance),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
reposMeta, manifestMetaMap, indexDataMap, err := metaDB.FilterTags(ctx,
|
var matchRepoName mTypes.FilterRepoTagFunc
|
||||||
func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool {
|
|
||||||
return repoMeta.Name == repo || repo == ""
|
if repo == "" {
|
||||||
})
|
matchRepoName = mTypes.AcceptAllRepoTag
|
||||||
|
} else {
|
||||||
|
matchRepoName = func(repoName, tag string) bool { return repoName == repo }
|
||||||
|
}
|
||||||
|
|
||||||
|
imageMeta, err := metaDB.FilterTags(ctx, matchRepoName, mTypes.AcceptAllImageMeta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedImagesResult{}, err
|
return &gql_generated.PaginatedImagesResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
imageList, pageInfo, err := convert.PaginatedRepoMeta2ImageSummaries(ctx, reposMeta, manifestMetaMap,
|
imageList, pageInfo, err := convert.PaginatedFullImageMeta2ImageSummaries(ctx, imageMeta, skip,
|
||||||
indexDataMap, skip, cveInfo, mTypes.Filter{}, pageInput)
|
cveInfo, mTypes.Filter{}, pageInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gql_generated.PaginatedImagesResult{}, err
|
return &gql_generated.PaginatedImagesResult{}, err
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,6 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"regexp"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@ -305,7 +304,7 @@ func getMockCveScanner(metaDB mTypes.MetaDB) cveinfo.Scanner {
|
|||||||
imageDir := repo
|
imageDir := repo
|
||||||
inputTag := reference
|
inputTag := reference
|
||||||
|
|
||||||
repoMeta, err := metaDB.GetRepoMeta(imageDir)
|
repoMeta, err := metaDB.GetRepoMeta(context.Background(), imageDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@ -328,19 +327,12 @@ func getMockCveScanner(metaDB mTypes.MetaDB) cveinfo.Scanner {
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
manifestData, err := metaDB.GetManifestData(manifestDigest)
|
manifestData, err := metaDB.GetImageMeta(manifestDigest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var manifestContent ispec.Manifest
|
for _, imageLayer := range manifestData.Manifests[0].Manifest.Layers {
|
||||||
|
|
||||||
err = json.Unmarshal(manifestData.ManifestBlob, &manifestContent)
|
|
||||||
if err != nil {
|
|
||||||
return false, zerr.ErrScanNotSupported
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, imageLayer := range manifestContent.Layers {
|
|
||||||
switch imageLayer.MediaType {
|
switch imageLayer.MediaType {
|
||||||
case ispec.MediaTypeImageLayerGzip, ispec.MediaTypeImageLayer, string(regTypes.DockerLayer):
|
case ispec.MediaTypeImageLayerGzip, ispec.MediaTypeImageLayer, string(regTypes.DockerLayer):
|
||||||
|
|
||||||
@ -1070,24 +1062,17 @@ func TestGetReferrersGQL(t *testing.T) {
|
|||||||
defer ctlrManager.StopServer()
|
defer ctlrManager.StopServer()
|
||||||
|
|
||||||
// Upload the index referrer
|
// Upload the index referrer
|
||||||
|
targetImg := CreateRandomImage()
|
||||||
targetImg, err := deprecated.GetRandomImage() //nolint:staticcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
targetDigest := targetImg.Digest()
|
targetDigest := targetImg.Digest()
|
||||||
|
|
||||||
err = UploadImage(targetImg, baseURL, "repo", targetDigest.String())
|
err := UploadImage(targetImg, baseURL, "repo", targetImg.DigestStr())
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
indexReferrer, err := deprecated.GetRandomMultiarchImage("ref") //nolint:staticcheck
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
artifactType := "com.artifact.art/type"
|
artifactType := "com.artifact.art/type"
|
||||||
indexReferrer.Index.ArtifactType = artifactType
|
indexReferrer := CreateMultiarchWith().RandomImages(2).
|
||||||
indexReferrer.Index.Subject = &ispec.Descriptor{
|
ArtifactType(artifactType).
|
||||||
MediaType: ispec.MediaTypeImageManifest,
|
Subject(targetImg.DescriptorRef()).
|
||||||
Digest: targetDigest,
|
Build()
|
||||||
}
|
|
||||||
|
|
||||||
indexReferrerDigest := indexReferrer.Digest()
|
indexReferrerDigest := indexReferrer.Digest()
|
||||||
|
|
||||||
err = UploadMultiarchImage(indexReferrer, baseURL, "repo", "ref")
|
err = UploadMultiarchImage(indexReferrer, baseURL, "repo", "ref")
|
||||||
@ -3203,7 +3188,9 @@ func TestGlobalSearch(t *testing.T) {
|
|||||||
Vendors
|
Vendors
|
||||||
NewestImage {
|
NewestImage {
|
||||||
RepoName Tag LastUpdated Size
|
RepoName Tag LastUpdated Size
|
||||||
|
Digest
|
||||||
Manifests{
|
Manifests{
|
||||||
|
Digest ConfigDigest
|
||||||
LastUpdated Size
|
LastUpdated Size
|
||||||
Platform { Os Arch }
|
Platform { Os Arch }
|
||||||
History {
|
History {
|
||||||
@ -4495,67 +4482,24 @@ func TestMetaDBWhenPushingImages(t *testing.T) {
|
|||||||
ctlrManager.StartAndWait(port)
|
ctlrManager.StartAndWait(port)
|
||||||
defer ctlrManager.StopServer()
|
defer ctlrManager.StopServer()
|
||||||
|
|
||||||
Convey("SetManifestMeta fails", func() {
|
|
||||||
ctlr.MetaDB = mocks.MetaDBMock{
|
|
||||||
SetManifestDataFn: func(manifestDigest godigest.Digest, mm mTypes.ManifestData) error {
|
|
||||||
return ErrTestError
|
|
||||||
},
|
|
||||||
}
|
|
||||||
config1, layers1, manifest1, err := deprecated.GetImageComponents(100) //nolint:staticcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
configBlob, err := json.Marshal(config1)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
ctlr.StoreController.DefaultStore = mocks.MockedImageStore{
|
|
||||||
NewBlobUploadFn: ctlr.StoreController.DefaultStore.NewBlobUpload,
|
|
||||||
PutBlobChunkFn: ctlr.StoreController.DefaultStore.PutBlobChunk,
|
|
||||||
GetBlobContentFn: func(repo string, digest godigest.Digest) ([]byte, error) {
|
|
||||||
return configBlob, nil
|
|
||||||
},
|
|
||||||
DeleteImageManifestFn: func(repo, reference string, dc bool) error {
|
|
||||||
return ErrTestError
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = UploadImage(
|
|
||||||
Image{
|
|
||||||
Manifest: manifest1,
|
|
||||||
Config: config1,
|
|
||||||
Layers: layers1,
|
|
||||||
}, baseURL, "repo1", "1.0.1",
|
|
||||||
)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SetManifestMeta succeeds but SetRepoReference fails", func() {
|
Convey("SetManifestMeta succeeds but SetRepoReference fails", func() {
|
||||||
ctlr.MetaDB = mocks.MetaDBMock{
|
ctlr.MetaDB = mocks.MetaDBMock{
|
||||||
SetRepoReferenceFn: func(repo, reference string, manifestDigest godigest.Digest, mediaType string) error {
|
SetRepoReferenceFn: func(repo, reference string, imageMeta mTypes.ImageMeta) error {
|
||||||
return ErrTestError
|
return ErrTestError
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
config1, layers1, manifest1, err := deprecated.GetImageComponents(100) //nolint:staticcheck
|
image := CreateRandomImage()
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
configBlob, err := json.Marshal(config1)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
ctlr.StoreController.DefaultStore = mocks.MockedImageStore{
|
ctlr.StoreController.DefaultStore = mocks.MockedImageStore{
|
||||||
NewBlobUploadFn: ctlr.StoreController.DefaultStore.NewBlobUpload,
|
NewBlobUploadFn: ctlr.StoreController.DefaultStore.NewBlobUpload,
|
||||||
PutBlobChunkFn: ctlr.StoreController.DefaultStore.PutBlobChunk,
|
PutBlobChunkFn: ctlr.StoreController.DefaultStore.PutBlobChunk,
|
||||||
GetBlobContentFn: func(repo string, digest godigest.Digest) ([]byte, error) {
|
GetBlobContentFn: func(repo string, digest godigest.Digest) ([]byte, error) {
|
||||||
return configBlob, nil
|
return image.ConfigDescriptor.Data, nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = UploadImage(
|
err := UploadImage(image, baseURL, "repo1", "1.0.1")
|
||||||
Image{
|
|
||||||
Manifest: manifest1,
|
|
||||||
Config: config1,
|
|
||||||
Layers: layers1,
|
|
||||||
}, baseURL, "repo1", "1.0.1",
|
|
||||||
)
|
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -4590,15 +4534,9 @@ func RunMetaDBIndexTests(baseURL, port string) {
|
|||||||
Convey("Push test index", func() {
|
Convey("Push test index", func() {
|
||||||
const repo = "repo"
|
const repo = "repo"
|
||||||
|
|
||||||
multiarchImage, err := deprecated.GetRandomMultiarchImage("tag1") //nolint:staticcheck
|
multiarchImage := CreateRandomMultiarch()
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
indexBlob, err := json.Marshal(multiarchImage.Index)
|
err := UploadMultiarchImage(multiarchImage, baseURL, repo, "tag1")
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
indexDigest := godigest.FromBytes(indexBlob)
|
|
||||||
|
|
||||||
err = UploadMultiarchImage(multiarchImage, baseURL, repo, "tag1")
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
query := `
|
query := `
|
||||||
@ -4634,7 +4572,7 @@ func RunMetaDBIndexTests(baseURL, port string) {
|
|||||||
responseImage := responseImages[0]
|
responseImage := responseImages[0]
|
||||||
So(len(responseImage.Manifests), ShouldEqual, 3)
|
So(len(responseImage.Manifests), ShouldEqual, 3)
|
||||||
|
|
||||||
err = signature.SignImageUsingCosign(fmt.Sprintf("repo@%s", indexDigest), port)
|
err = signature.SignImageUsingCosign(fmt.Sprintf("repo@%s", multiarchImage.DigestStr()), port)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(query))
|
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(query))
|
||||||
@ -4654,7 +4592,7 @@ func RunMetaDBIndexTests(baseURL, port string) {
|
|||||||
So(responseImage.IsSigned, ShouldBeTrue)
|
So(responseImage.IsSigned, ShouldBeTrue)
|
||||||
|
|
||||||
// remove signature
|
// remove signature
|
||||||
cosignTag := "sha256-" + indexDigest.Encoded() + ".sig"
|
cosignTag := "sha256-" + multiarchImage.Digest().Encoded() + ".sig"
|
||||||
_, err = resty.R().Delete(baseURL + "/v2/" + "repo" + "/manifests/" + cosignTag)
|
_, err = resty.R().Delete(baseURL + "/v2/" + "repo" + "/manifests/" + cosignTag)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
@ -5409,9 +5347,7 @@ func TestMetaDBWhenDeletingImages(t *testing.T) {
|
|||||||
for _, manifest := range indexContent.Manifests {
|
for _, manifest := range indexContent.Manifests {
|
||||||
tag := manifest.Annotations[ispec.AnnotationRefName]
|
tag := manifest.Annotations[ispec.AnnotationRefName]
|
||||||
|
|
||||||
cosignTagRule := regexp.MustCompile(`sha256\-.+\.sig`)
|
if zcommon.IsCosignTag(tag) {
|
||||||
|
|
||||||
if cosignTagRule.MatchString(tag) {
|
|
||||||
signatureTag = tag
|
signatureTag = tag
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5685,7 +5621,10 @@ func TestMetaDBWhenDeletingImages(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctlr.MetaDB = mocks.MetaDBMock{
|
ctlr.MetaDB = mocks.MetaDBMock{
|
||||||
RemoveRepoReferenceFn: func(repo, reference string, manifestDigest godigest.Digest) error { return ErrTestError },
|
RemoveRepoReferenceFn: func(repo, reference string, manifestDigest godigest.Digest,
|
||||||
|
) error {
|
||||||
|
return ErrTestError
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err = resty.R().Delete(baseURL + "/v2/" + "repo1" + "/manifests/" +
|
resp, err = resty.R().Delete(baseURL + "/v2/" + "repo1" + "/manifests/" +
|
||||||
@ -6438,16 +6377,6 @@ func TestUploadingArtifactsWithDifferentMediaType(t *testing.T) {
|
|||||||
err = UploadImage(defaultImage, baseURL, "repo", "default-image")
|
err = UploadImage(defaultImage, baseURL, "repo", "default-image")
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
manifestData, err := ctlr.MetaDB.GetManifestData(imageWithIncompatibleConfig.ManifestDescriptor.Digest)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(manifestData.ConfigBlob, ShouldEqual, imageWithIncompatibleConfig.ConfigDescriptor.Data)
|
|
||||||
So(manifestData.ManifestBlob, ShouldEqual, imageWithIncompatibleConfig.ManifestDescriptor.Data)
|
|
||||||
|
|
||||||
manifestData, err = ctlr.MetaDB.GetManifestData(defaultImage.ManifestDescriptor.Digest)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(manifestData.ConfigBlob, ShouldEqual, defaultImage.ConfigDescriptor.Data)
|
|
||||||
So(manifestData.ManifestBlob, ShouldEqual, defaultImage.ManifestDescriptor.Data)
|
|
||||||
|
|
||||||
query := `
|
query := `
|
||||||
{
|
{
|
||||||
GlobalSearch(query:"repo:incompatible-image"){
|
GlobalSearch(query:"repo:incompatible-image"){
|
||||||
|
@ -18,13 +18,11 @@ import (
|
|||||||
"zotregistry.io/zot/pkg/api/constants"
|
"zotregistry.io/zot/pkg/api/constants"
|
||||||
"zotregistry.io/zot/pkg/common"
|
"zotregistry.io/zot/pkg/common"
|
||||||
extconf "zotregistry.io/zot/pkg/extensions/config"
|
extconf "zotregistry.io/zot/pkg/extensions/config"
|
||||||
"zotregistry.io/zot/pkg/extensions/monitoring"
|
|
||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
"zotregistry.io/zot/pkg/storage"
|
|
||||||
"zotregistry.io/zot/pkg/storage/local"
|
|
||||||
test "zotregistry.io/zot/pkg/test/common"
|
test "zotregistry.io/zot/pkg/test/common"
|
||||||
"zotregistry.io/zot/pkg/test/deprecated"
|
"zotregistry.io/zot/pkg/test/deprecated"
|
||||||
. "zotregistry.io/zot/pkg/test/image-utils"
|
. "zotregistry.io/zot/pkg/test/image-utils"
|
||||||
|
. "zotregistry.io/zot/pkg/test/oci-utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
//nolint:dupl
|
//nolint:dupl
|
||||||
@ -535,25 +533,15 @@ func TestChangingRepoState(t *testing.T) {
|
|||||||
|
|
||||||
ctlr := api.NewController(conf)
|
ctlr := api.NewController(conf)
|
||||||
|
|
||||||
img, err := deprecated.GetRandomImage() //nolint:staticcheck
|
img := CreateRandomImage()
|
||||||
|
storeCtlr := GetDefaultStoreController(conf.Storage.RootDirectory, log.NewLogger("debug", ""))
|
||||||
|
|
||||||
|
err := WriteImageToFileSystem(img, accesibleRepo, "tag", storeCtlr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------ Create the test repos
|
err = WriteImageToFileSystem(img, forbiddenRepo, "tag", storeCtlr)
|
||||||
defaultStore := local.NewImageStore(conf.Storage.RootDirectory, false, false,
|
|
||||||
log.NewLogger("debug", ""), monitoring.NewMetricsServer(false, log.NewLogger("debug", "")), nil, nil)
|
|
||||||
|
|
||||||
err = WriteImageToFileSystem(img, accesibleRepo, "tag", storage.StoreController{
|
|
||||||
DefaultStore: defaultStore,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
err = WriteImageToFileSystem(img, forbiddenRepo, "tag", storage.StoreController{
|
|
||||||
DefaultStore: defaultStore,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
@ -153,21 +153,9 @@ func (ref CosignReference) SyncReferences(ctx context.Context, localRepo, remote
|
|||||||
ref.log.Debug().Str("repository", localRepo).Str("subject", subjectDigestStr).
|
ref.log.Debug().Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||||
Msg("metaDB: trying to sync cosign reference for image")
|
Msg("metaDB: trying to sync cosign reference for image")
|
||||||
|
|
||||||
isSig, sigType, signedManifestDig, err := storage.CheckIsImageSignature(localRepo, manifestBuf,
|
|
||||||
cosignTag)
|
|
||||||
if err != nil {
|
|
||||||
return refsDigests, fmt.Errorf("failed to check if cosign reference '%s@%s' is a signature: %w", localRepo,
|
|
||||||
cosignTag, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if isSig {
|
|
||||||
err = addSigToMeta(ref.metaDB, localRepo, sigType, cosignTag, signedManifestDig, referenceDigest,
|
|
||||||
manifestBuf, imageStore, ref.log)
|
|
||||||
} else {
|
|
||||||
err = meta.SetImageMetaFromInput(localRepo, cosignTag, ispec.MediaTypeImageManifest,
|
err = meta.SetImageMetaFromInput(localRepo, cosignTag, ispec.MediaTypeImageManifest,
|
||||||
referenceDigest, manifestBuf, ref.storeController.GetImageStore(localRepo),
|
referenceDigest, manifestBuf, ref.storeController.GetImageStore(localRepo),
|
||||||
ref.metaDB, ref.log)
|
ref.metaDB, ref.log)
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return refsDigests, fmt.Errorf("failed to set metadata for cosign reference in '%s@%s': %w",
|
return refsDigests, fmt.Errorf("failed to set metadata for cosign reference in '%s@%s': %w",
|
||||||
|
@ -137,22 +137,9 @@ func (ref OciReferences) SyncReferences(ctx context.Context, localRepo, remoteRe
|
|||||||
ref.log.Debug().Str("repository", localRepo).Str("subject", subjectDigestStr).
|
ref.log.Debug().Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||||
Msg("metaDB: trying to add oci references for image")
|
Msg("metaDB: trying to add oci references for image")
|
||||||
|
|
||||||
isSig, sigType, signedManifestDig, err := storage.CheckIsImageSignature(localRepo, referenceBuf,
|
|
||||||
referrer.Digest.String())
|
|
||||||
if err != nil {
|
|
||||||
return refsDigests, fmt.Errorf("failed to check if oci reference '%s@%s' is a signature: %w", localRepo,
|
|
||||||
referrer.Digest.String(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if isSig {
|
|
||||||
err = addSigToMeta(ref.metaDB, localRepo, sigType, referrer.Digest.String(), signedManifestDig, referenceDigest,
|
|
||||||
referenceBuf, imageStore, ref.log)
|
|
||||||
} else {
|
|
||||||
err = meta.SetImageMetaFromInput(localRepo, referenceDigest.String(), referrer.MediaType,
|
err = meta.SetImageMetaFromInput(localRepo, referenceDigest.String(), referrer.MediaType,
|
||||||
referenceDigest, referenceBuf, ref.storeController.GetImageStore(localRepo),
|
referenceDigest, referenceBuf, ref.storeController.GetImageStore(localRepo),
|
||||||
ref.metaDB, ref.log)
|
ref.metaDB, ref.log)
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return refsDigests, fmt.Errorf("failed to set metadata for oci reference in '%s@%s': %w",
|
return refsDigests, fmt.Errorf("failed to set metadata for oci reference in '%s@%s': %w",
|
||||||
localRepo, subjectDigestStr, err)
|
localRepo, subjectDigestStr, err)
|
||||||
|
@ -113,22 +113,9 @@ func (ref TagReferences) SyncReferences(ctx context.Context, localRepo, remoteRe
|
|||||||
ref.log.Debug().Str("repository", localRepo).Str("subject", subjectDigestStr).
|
ref.log.Debug().Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||||
Msg("metaDB: trying to add oci references for image")
|
Msg("metaDB: trying to add oci references for image")
|
||||||
|
|
||||||
isSig, sigType, signedManifestDig, err := storage.CheckIsImageSignature(localRepo, referenceBuf,
|
|
||||||
referrer.Digest.String())
|
|
||||||
if err != nil {
|
|
||||||
return refsDigests, fmt.Errorf("failed to check if oci reference '%s@%s' is a signature: %w", localRepo,
|
|
||||||
referrer.Digest.String(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if isSig {
|
|
||||||
err = addSigToMeta(ref.metaDB, localRepo, sigType, referrer.Digest.String(), signedManifestDig, referenceDigest,
|
|
||||||
referenceBuf, imageStore, ref.log)
|
|
||||||
} else {
|
|
||||||
err = meta.SetImageMetaFromInput(localRepo, referenceDigest.String(), referrer.MediaType,
|
err = meta.SetImageMetaFromInput(localRepo, referenceDigest.String(), referrer.MediaType,
|
||||||
referenceDigest, referenceBuf, ref.storeController.GetImageStore(localRepo),
|
referenceDigest, referenceBuf, ref.storeController.GetImageStore(localRepo),
|
||||||
ref.metaDB, ref.log)
|
ref.metaDB, ref.log)
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return refsDigests, fmt.Errorf("failed to set metadata for oci reference in '%s@%s': %w",
|
return refsDigests, fmt.Errorf("failed to set metadata for oci reference in '%s@%s': %w",
|
||||||
localRepo, subjectDigestStr, err)
|
localRepo, subjectDigestStr, err)
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"zotregistry.io/zot/pkg/extensions/monitoring"
|
"zotregistry.io/zot/pkg/extensions/monitoring"
|
||||||
client "zotregistry.io/zot/pkg/extensions/sync/httpclient"
|
client "zotregistry.io/zot/pkg/extensions/sync/httpclient"
|
||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
|
mTypes "zotregistry.io/zot/pkg/meta/types"
|
||||||
"zotregistry.io/zot/pkg/storage"
|
"zotregistry.io/zot/pkg/storage"
|
||||||
"zotregistry.io/zot/pkg/storage/cache"
|
"zotregistry.io/zot/pkg/storage/cache"
|
||||||
storageConstants "zotregistry.io/zot/pkg/storage/constants"
|
storageConstants "zotregistry.io/zot/pkg/storage/constants"
|
||||||
@ -336,8 +337,8 @@ func TestLocalRegistry(t *testing.T) {
|
|||||||
|
|
||||||
Convey("trigger metaDB error on index manifest in CommitImage()", func() {
|
Convey("trigger metaDB error on index manifest in CommitImage()", func() {
|
||||||
registry := NewLocalRegistry(storage.StoreController{DefaultStore: syncImgStore}, mocks.MetaDBMock{
|
registry := NewLocalRegistry(storage.StoreController{DefaultStore: syncImgStore}, mocks.MetaDBMock{
|
||||||
SetRepoReferenceFn: func(repo, Reference string, manifestDigest godigest.Digest, mediaType string) error {
|
SetRepoReferenceFn: func(repo string, reference string, imageMeta mTypes.ImageMeta) error {
|
||||||
if Reference == "1.0" {
|
if reference == "1.0" {
|
||||||
return zerr.ErrRepoMetaNotFound
|
return zerr.ErrRepoMetaNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,7 +352,7 @@ func TestLocalRegistry(t *testing.T) {
|
|||||||
|
|
||||||
Convey("trigger metaDB error on image manifest in CommitImage()", func() {
|
Convey("trigger metaDB error on image manifest in CommitImage()", func() {
|
||||||
registry := NewLocalRegistry(storage.StoreController{DefaultStore: syncImgStore}, mocks.MetaDBMock{
|
registry := NewLocalRegistry(storage.StoreController{DefaultStore: syncImgStore}, mocks.MetaDBMock{
|
||||||
SetRepoReferenceFn: func(repo, Reference string, manifestDigest godigest.Digest, mediaType string) error {
|
SetRepoReferenceFn: func(repo, reference string, imageMeta mTypes.ImageMeta) error {
|
||||||
return zerr.ErrRepoMetaNotFound
|
return zerr.ErrRepoMetaNotFound
|
||||||
},
|
},
|
||||||
}, log)
|
}, log)
|
||||||
|
@ -877,9 +877,7 @@ func TestOnDemand(t *testing.T) {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
SetRepoReferenceFn: func(repo, reference string, manifestDigest godigest.Digest,
|
SetRepoReferenceFn: func(repo, reference string, imageMeta mTypes.ImageMeta) error {
|
||||||
mediaType string,
|
|
||||||
) error {
|
|
||||||
if strings.HasPrefix(reference, "sha256-") &&
|
if strings.HasPrefix(reference, "sha256-") &&
|
||||||
(strings.HasSuffix(reference, remote.SignatureTagSuffix) ||
|
(strings.HasSuffix(reference, remote.SignatureTagSuffix) ||
|
||||||
strings.HasSuffix(reference, remote.SBOMTagSuffix)) ||
|
strings.HasSuffix(reference, remote.SBOMTagSuffix)) ||
|
||||||
@ -1019,8 +1017,8 @@ func TestOnDemand(t *testing.T) {
|
|||||||
|
|
||||||
// metadb fails for syncReferrersTag"
|
// metadb fails for syncReferrersTag"
|
||||||
dctlr.MetaDB = mocks.MetaDBMock{
|
dctlr.MetaDB = mocks.MetaDBMock{
|
||||||
SetManifestDataFn: func(manifestDigest godigest.Digest, mm mTypes.ManifestData) error {
|
SetRepoReferenceFn: func(repo, reference string, imageMeta mTypes.ImageMeta) error {
|
||||||
if manifestDigest.String() == ociRefImage.ManifestDescriptor.Digest.String() {
|
if imageMeta.Digest.String() == ociRefImage.ManifestDescriptor.Digest.String() {
|
||||||
return sync.ErrTestError
|
return sync.ErrTestError
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4670,7 +4668,7 @@ func TestSyncedSignaturesMetaDB(t *testing.T) {
|
|||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||||||
|
|
||||||
repoMeta, err := dctlr.MetaDB.GetRepoMeta(repoName)
|
repoMeta, err := dctlr.MetaDB.GetRepoMeta(context.Background(), repoName)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(repoMeta.Tags, ShouldContainKey, tag)
|
So(repoMeta.Tags, ShouldContainKey, tag)
|
||||||
So(len(repoMeta.Tags), ShouldEqual, 1)
|
So(len(repoMeta.Tags), ShouldEqual, 1)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -4,29 +4,25 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
|
||||||
"math"
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
"go.etcd.io/bbolt"
|
"go.etcd.io/bbolt"
|
||||||
|
|
||||||
zerr "zotregistry.io/zot/errors"
|
zerr "zotregistry.io/zot/errors"
|
||||||
zcommon "zotregistry.io/zot/pkg/common"
|
|
||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
"zotregistry.io/zot/pkg/meta/boltdb"
|
"zotregistry.io/zot/pkg/meta/boltdb"
|
||||||
mTypes "zotregistry.io/zot/pkg/meta/types"
|
mTypes "zotregistry.io/zot/pkg/meta/types"
|
||||||
reqCtx "zotregistry.io/zot/pkg/requestcontext"
|
reqCtx "zotregistry.io/zot/pkg/requestcontext"
|
||||||
. "zotregistry.io/zot/pkg/test/image-utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type imgTrustStore struct{}
|
type imgTrustStore struct{}
|
||||||
|
|
||||||
func (its imgTrustStore) VerifySignature(
|
func (its imgTrustStore) VerifySignature(
|
||||||
signatureType string, rawSignature []byte, sigKey string, manifestDigest digest.Digest, manifestContent []byte,
|
signatureType string, rawSignature []byte, sigKey string, manifestDigest digest.Digest, imageMeta mTypes.ImageMeta,
|
||||||
repo string,
|
repo string,
|
||||||
) (string, time.Time, bool, error) {
|
) (string, time.Time, bool, error) {
|
||||||
return "", time.Time{}, false, nil
|
return "", time.Time{}, false, nil
|
||||||
@ -47,14 +43,6 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
|
|
||||||
boltdbWrapper.SetImageTrustStore(imgTrustStore{})
|
boltdbWrapper.SetImageTrustStore(imgTrustStore{})
|
||||||
|
|
||||||
repoMeta := mTypes.RepoMetadata{
|
|
||||||
Tags: map[string]mTypes.Descriptor{},
|
|
||||||
Signatures: map[string]mTypes.ManifestSignatures{},
|
|
||||||
}
|
|
||||||
|
|
||||||
repoMetaBlob, err := json.Marshal(repoMeta)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
userAc := reqCtx.NewUserAccessControl()
|
userAc := reqCtx.NewUserAccessControl()
|
||||||
userAc.SetUsername("test")
|
userAc.SetUsername("test")
|
||||||
|
|
||||||
@ -245,604 +233,6 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("GetManifestData", func() {
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
dataBuck := tx.Bucket([]byte(boltdb.ManifestDataBucket))
|
|
||||||
|
|
||||||
return dataBuck.Put([]byte("digest1"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, err = boltdbWrapper.GetManifestData("digest1")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
_, err = boltdbWrapper.GetManifestMeta("repo1", "digest1")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SetManifestMeta", func() {
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
dataBuck := tx.Bucket([]byte(boltdb.ManifestDataBucket))
|
|
||||||
|
|
||||||
err := dataBuck.Put([]byte("digest1"), repoMetaBlob)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.SetManifestMeta("repo1", "digest1", mTypes.ManifestMetadata{})
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
_, err = boltdbWrapper.GetManifestMeta("repo1", "digest1")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("FilterRepos", func() {
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
buck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
err := buck.Put([]byte("badRepo"), []byte("bad repo"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = boltdbWrapper.FilterRepos(context.Background(),
|
|
||||||
func(repoMeta mTypes.RepoMetadata) bool { return true })
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SetReferrer", func() {
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.SetReferrer("repo", "ref", mTypes.ReferrerInfo{})
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("DeleteReferrer", func() {
|
|
||||||
Convey("RepoMeta not found", func() {
|
|
||||||
err := boltdbWrapper.DeleteReferrer("r", "dig", "dig")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("bad repo meta blob", func() {
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.DeleteReferrer("repo", "dig", "dig")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SetRepoReference", func() {
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.SetRepoReference("repo1", "tag", "digest", ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetRepoMeta", func() {
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, err = boltdbWrapper.GetRepoMeta("repo1")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("DeleteRepoTag", func() {
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.DeleteRepoTag("repo1", "tag")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetReferrersInfo", func() {
|
|
||||||
_, err = boltdbWrapper.GetReferrersInfo("repo1", "tag", nil)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, err = boltdbWrapper.GetReferrersInfo("repo1", "tag", nil)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("IncrementRepoStars", func() {
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.IncrementRepoStars("repo2")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.IncrementRepoStars("repo1")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("DecrementRepoStars", func() {
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.DecrementRepoStars("repo2")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.DecrementRepoStars("repo1")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetRepoStars", func() {
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, err = boltdbWrapper.GetRepoStars("repo1")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetMultipleRepoMeta", func() {
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, err = boltdbWrapper.GetMultipleRepoMeta(context.TODO(), func(repoMeta mTypes.RepoMetadata) bool {
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("IncrementImageDownloads", func() {
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.IncrementImageDownloads("repo2", "tag")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.IncrementImageDownloads("repo1", "tag")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), repoMetaBlob)
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.IncrementImageDownloads("repo1", "tag")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("AddManifestSignature", func() {
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.AddManifestSignature("repo1", digest.FromString("dig"),
|
|
||||||
mTypes.SignatureMetadata{})
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), repoMetaBlob)
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
// signatures not found
|
|
||||||
err = boltdbWrapper.AddManifestSignature("repo1", digest.FromString("dig"),
|
|
||||||
mTypes.SignatureMetadata{})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
//
|
|
||||||
err = boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
repoMeta := mTypes.RepoMetadata{
|
|
||||||
Tags: map[string]mTypes.Descriptor{},
|
|
||||||
Signatures: map[string]mTypes.ManifestSignatures{
|
|
||||||
"digest1": {
|
|
||||||
"cosgin": {{}},
|
|
||||||
},
|
|
||||||
"digest2": {
|
|
||||||
"notation": {{}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
repoMetaBlob, err := json.Marshal(repoMeta)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), repoMetaBlob)
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.AddManifestSignature("repo1", digest.FromString("dig"),
|
|
||||||
mTypes.SignatureMetadata{
|
|
||||||
SignatureType: "cosign",
|
|
||||||
SignatureDigest: "digest1",
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.AddManifestSignature("repo1", digest.FromString("dig"),
|
|
||||||
mTypes.SignatureMetadata{
|
|
||||||
SignatureType: "cosign",
|
|
||||||
SignatureDigest: "digest2",
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
repoData, err := boltdbWrapper.GetRepoMeta("repo1")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
So(len(repoData.Signatures[string(digest.FromString("dig"))][zcommon.CosignSignature]),
|
|
||||||
ShouldEqual, 1)
|
|
||||||
So(repoData.Signatures[string(digest.FromString("dig"))][zcommon.CosignSignature][0].SignatureManifestDigest,
|
|
||||||
ShouldEqual, "digest2")
|
|
||||||
|
|
||||||
err = boltdbWrapper.AddManifestSignature("repo1", digest.FromString("dig"),
|
|
||||||
mTypes.SignatureMetadata{
|
|
||||||
SignatureType: "notation",
|
|
||||||
SignatureDigest: "digest2",
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("DeleteSignature", func() {
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.DeleteSignature("repo2", digest.FromString("dig"),
|
|
||||||
mTypes.SignatureMetadata{})
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.DeleteSignature("repo1", digest.FromString("dig"),
|
|
||||||
mTypes.SignatureMetadata{})
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
repoMeta := mTypes.RepoMetadata{
|
|
||||||
Tags: map[string]mTypes.Descriptor{},
|
|
||||||
Signatures: map[string]mTypes.ManifestSignatures{
|
|
||||||
"digest1": {
|
|
||||||
"cosgin": []mTypes.SignatureInfo{
|
|
||||||
{
|
|
||||||
SignatureManifestDigest: "sigDigest1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
SignatureManifestDigest: "sigDigest2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"digest2": {
|
|
||||||
"notation": {{}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
repoMetaBlob, err := json.Marshal(repoMeta)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), repoMetaBlob)
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.DeleteSignature("repo1", "digest1",
|
|
||||||
mTypes.SignatureMetadata{
|
|
||||||
SignatureType: "cosgin",
|
|
||||||
SignatureDigest: "sigDigest2",
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SearchRepos", func() {
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = boltdbWrapper.SearchRepos(context.Background(), "")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
dataBuck := tx.Bucket([]byte(boltdb.ManifestDataBucket))
|
|
||||||
|
|
||||||
err := dataBuck.Put([]byte("dig1"), []byte("wrong json"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
repoMeta := mTypes.RepoMetadata{
|
|
||||||
Name: "repo1",
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"tag1": {Digest: "dig1", MediaType: ispec.MediaTypeImageManifest},
|
|
||||||
},
|
|
||||||
Signatures: map[string]mTypes.ManifestSignatures{},
|
|
||||||
}
|
|
||||||
repoMetaBlob, err := json.Marshal(repoMeta)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = repoBuck.Put([]byte("repo1"), repoMetaBlob)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
repoMeta = mTypes.RepoMetadata{
|
|
||||||
Name: "repo2",
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"tag2": {Digest: "dig2", MediaType: ispec.MediaTypeImageManifest},
|
|
||||||
},
|
|
||||||
Signatures: map[string]mTypes.ManifestSignatures{},
|
|
||||||
}
|
|
||||||
repoMetaBlob, err = json.Marshal(repoMeta)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo2"), repoMetaBlob)
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = boltdbWrapper.SearchRepos(context.Background(), "repo1")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = boltdbWrapper.SearchRepos(context.Background(), "repo2")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Index Errors", func() {
|
|
||||||
Convey("Bad index data", func() {
|
|
||||||
indexDigest := digest.FromString("indexDigest")
|
|
||||||
|
|
||||||
err := boltdbWrapper.SetRepoReference("repo", "tag1", indexDigest, ispec.MediaTypeImageIndex) //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = setBadIndexData(boltdbWrapper.DB, indexDigest.String())
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = boltdbWrapper.SearchRepos(ctx, "")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = boltdbWrapper.SearchTags(ctx, "repo:")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Bad indexBlob in IndexData", func() {
|
|
||||||
indexDigest := digest.FromString("indexDigest")
|
|
||||||
|
|
||||||
err := boltdbWrapper.SetRepoReference("repo", "tag1", indexDigest, ispec.MediaTypeImageIndex) //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.SetIndexData(indexDigest, mTypes.IndexData{
|
|
||||||
IndexBlob: []byte("bad json"),
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = boltdbWrapper.SearchRepos(ctx, "")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = boltdbWrapper.SearchTags(ctx, "repo:")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SearchTags", func() {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = boltdbWrapper.SearchTags(ctx, "")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = boltdbWrapper.SearchTags(ctx, "repo1:")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
dataBuck := tx.Bucket([]byte(boltdb.ManifestDataBucket))
|
|
||||||
|
|
||||||
manifestMeta := mTypes.ManifestMetadata{
|
|
||||||
ManifestBlob: []byte("{}"),
|
|
||||||
ConfigBlob: []byte("wrong json"),
|
|
||||||
Signatures: mTypes.ManifestSignatures{},
|
|
||||||
}
|
|
||||||
|
|
||||||
manifestMetaBlob, err := json.Marshal(manifestMeta)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = dataBuck.Put([]byte("dig1"), manifestMetaBlob)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = dataBuck.Put([]byte("wrongManifestData"), []byte("wrong json"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// manifest data doesn't exist
|
|
||||||
repoMeta = mTypes.RepoMetadata{
|
|
||||||
Name: "repo1",
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"tag2": {Digest: "dig2", MediaType: ispec.MediaTypeImageManifest},
|
|
||||||
},
|
|
||||||
Signatures: map[string]mTypes.ManifestSignatures{},
|
|
||||||
}
|
|
||||||
repoMetaBlob, err = json.Marshal(repoMeta)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = repoBuck.Put([]byte("repo1"), repoMetaBlob)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// manifest data is wrong
|
|
||||||
repoMeta = mTypes.RepoMetadata{
|
|
||||||
Name: "repo2",
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"tag2": {Digest: "wrongManifestData", MediaType: ispec.MediaTypeImageManifest},
|
|
||||||
},
|
|
||||||
Signatures: map[string]mTypes.ManifestSignatures{},
|
|
||||||
}
|
|
||||||
repoMetaBlob, err = json.Marshal(repoMeta)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = repoBuck.Put([]byte("repo2"), repoMetaBlob)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
repoMeta = mTypes.RepoMetadata{
|
|
||||||
Name: "repo3",
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"tag1": {Digest: "dig1", MediaType: ispec.MediaTypeImageManifest},
|
|
||||||
},
|
|
||||||
Signatures: map[string]mTypes.ManifestSignatures{},
|
|
||||||
}
|
|
||||||
repoMetaBlob, err = json.Marshal(repoMeta)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo3"), repoMetaBlob)
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = boltdbWrapper.SearchTags(ctx, "repo1:")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = boltdbWrapper.SearchTags(ctx, "repo2:")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("FilterTags Index errors", func() {
|
|
||||||
Convey("FilterTags bad IndexData", func() {
|
|
||||||
indexDigest := digest.FromString("indexDigest")
|
|
||||||
|
|
||||||
err := boltdbWrapper.SetRepoReference("repo", "tag1", indexDigest, ispec.MediaTypeImageIndex) //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = setBadIndexData(boltdbWrapper.DB, indexDigest.String())
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = boltdbWrapper.FilterTags(ctx,
|
|
||||||
func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool { return true })
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("FilterTags bad indexBlob in IndexData", func() {
|
|
||||||
indexDigest := digest.FromString("indexDigest")
|
|
||||||
|
|
||||||
err := boltdbWrapper.SetRepoReference("repo", "tag1", indexDigest, ispec.MediaTypeImageIndex) //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.SetIndexData(indexDigest, mTypes.IndexData{
|
|
||||||
IndexBlob: []byte("bad json"),
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = boltdbWrapper.FilterTags(ctx,
|
|
||||||
func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool { return true })
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("FilterTags didn't match any index manifest", func() {
|
|
||||||
var (
|
|
||||||
indexDigest = digest.FromString("indexDigest")
|
|
||||||
manifestDigestFromIndex1 = digest.FromString("manifestDigestFromIndex1")
|
|
||||||
manifestDigestFromIndex2 = digest.FromString("manifestDigestFromIndex2")
|
|
||||||
)
|
|
||||||
|
|
||||||
err := boltdbWrapper.SetRepoReference("repo", "tag1", indexDigest, ispec.MediaTypeImageIndex) //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
indexBlob, err := GetIndexBlobWithManifests([]digest.Digest{
|
|
||||||
manifestDigestFromIndex1, manifestDigestFromIndex2,
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.SetIndexData(indexDigest, mTypes.IndexData{
|
|
||||||
IndexBlob: indexBlob,
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.SetManifestData(manifestDigestFromIndex1, mTypes.ManifestData{
|
|
||||||
ManifestBlob: []byte("{}"),
|
|
||||||
ConfigBlob: []byte("{}"),
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.SetManifestData(manifestDigestFromIndex2, mTypes.ManifestData{
|
|
||||||
ManifestBlob: []byte("{}"),
|
|
||||||
ConfigBlob: []byte("{}"),
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = boltdbWrapper.FilterTags(ctx,
|
|
||||||
func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool { return false })
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("ToggleStarRepo bad context errors", func() {
|
Convey("ToggleStarRepo bad context errors", func() {
|
||||||
uacKey := reqCtx.GetContextKey()
|
uacKey := reqCtx.GetContextKey()
|
||||||
ctx := context.WithValue(context.Background(), uacKey, "bad context")
|
ctx := context.WithValue(context.Background(), uacKey, "bad context")
|
||||||
@ -860,7 +250,7 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
ctx := userAc.DeriveContext(context.Background())
|
ctx := userAc.DeriveContext(context.Background())
|
||||||
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
repoBuck := tx.Bucket([]byte(boltdb.RepoMetaBuck))
|
||||||
|
|
||||||
err := repoBuck.Put([]byte("repo"), []byte("bad repo"))
|
err := repoBuck.Put([]byte("repo"), []byte("bad repo"))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
@ -976,23 +366,6 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("Unsuported type", func() {
|
|
||||||
digest := digest.FromString("digest")
|
|
||||||
|
|
||||||
err := boltdbWrapper.SetRepoReference("repo", "tag1", digest, "invalid type") //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = boltdbWrapper.SearchRepos(ctx, "")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = boltdbWrapper.SearchTags(ctx, "repo:")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = boltdbWrapper.FilterTags(ctx,
|
|
||||||
func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool { return true })
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetUserRepoMeta unmarshal error", func() {
|
Convey("GetUserRepoMeta unmarshal error", func() {
|
||||||
userAc := reqCtx.NewUserAccessControl()
|
userAc := reqCtx.NewUserAccessControl()
|
||||||
userAc.SetUsername("username")
|
userAc.SetUsername("username")
|
||||||
@ -1002,7 +375,7 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
ctx := userAc.DeriveContext(context.Background())
|
ctx := userAc.DeriveContext(context.Background())
|
||||||
|
|
||||||
err = boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
err = boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
repoBuck := tx.Bucket([]byte(boltdb.RepoMetaBuck))
|
||||||
|
|
||||||
err := repoBuck.Put([]byte("repo"), []byte("bad repo"))
|
err := repoBuck.Put([]byte("repo"), []byte("bad repo"))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
@ -1011,78 +384,8 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
})
|
})
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
_, err := boltdbWrapper.GetUserRepoMeta(ctx, "repo")
|
_, err := boltdbWrapper.GetRepoMeta(ctx, "repo")
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("UpdateSignaturesValidity", func() {
|
|
||||||
Convey("manifestMeta of signed manifest not found", func() {
|
|
||||||
err := boltdbWrapper.UpdateSignaturesValidity("repo", digest.FromString("dig"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("repoMeta of signed manifest not found", func() {
|
|
||||||
// repo Meta not found
|
|
||||||
err := boltdbWrapper.SetManifestData(digest.FromString("dig"), mTypes.ManifestData{
|
|
||||||
ManifestBlob: []byte("Bad Manifest"),
|
|
||||||
ConfigBlob: []byte("Bad Manifest"),
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.UpdateSignaturesValidity("repo", digest.FromString("dig"))
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("manifest - bad content", func() {
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
dataBuck := tx.Bucket([]byte(boltdb.ManifestDataBucket))
|
|
||||||
|
|
||||||
return dataBuck.Put([]byte("digest1"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.UpdateSignaturesValidity("repo1", "digest1")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("index - bad content", func() {
|
|
||||||
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
dataBuck := tx.Bucket([]byte(boltdb.IndexDataBucket))
|
|
||||||
|
|
||||||
return dataBuck.Put([]byte("digest1"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.UpdateSignaturesValidity("repo1", "digest1")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("repo - bad content", func() {
|
|
||||||
// repo Meta not found
|
|
||||||
err := boltdbWrapper.SetManifestData(digest.FromString("dig"), mTypes.ManifestData{
|
|
||||||
ManifestBlob: []byte("Bad Manifest"),
|
|
||||||
ConfigBlob: []byte("Bad Manifest"),
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
repoBuck := tx.Bucket([]byte(boltdb.RepoMetadataBucket))
|
|
||||||
|
|
||||||
return repoBuck.Put([]byte("repo1"), []byte("wrong json"))
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = boltdbWrapper.UpdateSignaturesValidity("repo1", digest.FromString("dig"))
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func setBadIndexData(dB *bbolt.DB, digest string) error {
|
|
||||||
return dB.Update(func(tx *bbolt.Tx) error {
|
|
||||||
indexDataBuck := tx.Bucket([]byte(boltdb.IndexDataBucket))
|
|
||||||
|
|
||||||
return indexDataBuck.Put([]byte(digest), []byte("bad json"))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,9 @@ package boltdb
|
|||||||
|
|
||||||
// MetadataDB.
|
// MetadataDB.
|
||||||
const (
|
const (
|
||||||
ManifestDataBucket = "ManifestData"
|
ImageMetaBuck = "ImageMeta"
|
||||||
IndexDataBucket = "IndexData"
|
RepoMetaBuck = "RepoMeta"
|
||||||
RepoMetadataBucket = "RepoMetadata"
|
RepoBlobsBuck = "RepoBlobsMeta"
|
||||||
UserDataBucket = "UserData"
|
UserDataBucket = "UserData"
|
||||||
VersionBucket = "Version"
|
VersionBucket = "Version"
|
||||||
UserAPIKeysBucket = "UserAPIKeys"
|
UserAPIKeysBucket = "UserAPIKeys"
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -10,28 +8,23 @@ import (
|
|||||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
|
||||||
zerr "zotregistry.io/zot/errors"
|
zerr "zotregistry.io/zot/errors"
|
||||||
|
zcommon "zotregistry.io/zot/pkg/common"
|
||||||
|
mConvert "zotregistry.io/zot/pkg/meta/convert"
|
||||||
|
proto_go "zotregistry.io/zot/pkg/meta/proto/gen"
|
||||||
mTypes "zotregistry.io/zot/pkg/meta/types"
|
mTypes "zotregistry.io/zot/pkg/meta/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func UpdateManifestMeta(repoMeta mTypes.RepoMetadata, manifestDigest godigest.Digest,
|
func SignatureAlreadyExists(signatureSlice []mTypes.SignatureInfo, sm mTypes.SignatureMetadata) bool {
|
||||||
manifestMeta mTypes.ManifestMetadata,
|
for _, sigInfo := range signatureSlice {
|
||||||
) mTypes.RepoMetadata {
|
if sm.SignatureDigest == sigInfo.SignatureManifestDigest {
|
||||||
updatedRepoMeta := repoMeta
|
return true
|
||||||
|
}
|
||||||
updatedStatistics := repoMeta.Statistics[manifestDigest.String()]
|
|
||||||
updatedStatistics.DownloadCount = manifestMeta.DownloadCount
|
|
||||||
updatedRepoMeta.Statistics[manifestDigest.String()] = updatedStatistics
|
|
||||||
|
|
||||||
if manifestMeta.Signatures == nil {
|
|
||||||
manifestMeta.Signatures = mTypes.ManifestSignatures{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updatedRepoMeta.Signatures[manifestDigest.String()] = manifestMeta.Signatures
|
return false
|
||||||
|
|
||||||
return updatedRepoMeta
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func SignatureAlreadyExists(signatureSlice []mTypes.SignatureInfo, sm mTypes.SignatureMetadata) bool {
|
func ProtoSignatureAlreadyExists(signatureSlice []*proto_go.SignatureInfo, sm mTypes.SignatureMetadata) bool {
|
||||||
for _, sigInfo := range signatureSlice {
|
for _, sigInfo := range signatureSlice {
|
||||||
if sm.SignatureDigest == sigInfo.SignatureManifestDigest {
|
if sm.SignatureDigest == sigInfo.SignatureManifestDigest {
|
||||||
return true
|
return true
|
||||||
@ -74,7 +67,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// RankRepoName associates a rank to a given repoName given a searchText.
|
// RankRepoName associates a rank to a given repoName given a searchText.
|
||||||
// The imporance of the value grows inversly proportional to the int value it has.
|
// The importance of the value grows inversely proportional to the int value it has.
|
||||||
// For example: rank(1) > rank(10) > rank(100)...
|
// For example: rank(1) > rank(10) > rank(100)...
|
||||||
func RankRepoName(searchText string, repoName string) int {
|
func RankRepoName(searchText string, repoName string) int {
|
||||||
searchText = strings.Trim(searchText, "/")
|
searchText = strings.Trim(searchText, "/")
|
||||||
@ -89,7 +82,7 @@ func RankRepoName(searchText string, repoName string) int {
|
|||||||
return perfectMatchPriority
|
return perfectMatchPriority
|
||||||
}
|
}
|
||||||
|
|
||||||
// searchText containst just 1 diretory name
|
// searchText contains just 1 directory name
|
||||||
if len(searchTextSlice) == 1 {
|
if len(searchTextSlice) == 1 {
|
||||||
lastNameInRepoPath := repoNameSlice[len(repoNameSlice)-1]
|
lastNameInRepoPath := repoNameSlice[len(repoNameSlice)-1]
|
||||||
|
|
||||||
@ -157,21 +150,6 @@ func GetRepoTag(searchText string) (string, string, error) {
|
|||||||
return repo, tag, nil
|
return repo, tag, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
func MatchesArtifactTypes(descriptorMediaType string, artifactTypes []string) bool {
|
||||||
if len(artifactTypes) == 0 {
|
if len(artifactTypes) == 0 {
|
||||||
return true
|
return true
|
||||||
@ -208,139 +186,199 @@ func CheckImageLastUpdated(repoLastUpdated time.Time, isSigned bool, noImageChec
|
|||||||
return repoLastUpdated, noImageChecked, isSigned
|
return repoLastUpdated, noImageChecked, isSigned
|
||||||
}
|
}
|
||||||
|
|
||||||
func FilterDataByRepo(foundRepos []mTypes.RepoMetadata, manifestMetadataMap map[string]mTypes.ManifestMetadata,
|
func AddImageMetaToRepoMeta(repoMeta *proto_go.RepoMeta, repoBlobs *proto_go.RepoBlobs, reference string,
|
||||||
indexDataMap map[string]mTypes.IndexData,
|
imageMeta mTypes.ImageMeta,
|
||||||
) (map[string]mTypes.ManifestMetadata, map[string]mTypes.IndexData, error) {
|
) (*proto_go.RepoMeta, *proto_go.RepoBlobs, error) {
|
||||||
var (
|
switch imageMeta.MediaType {
|
||||||
foundManifestMetadataMap = make(map[string]mTypes.ManifestMetadata)
|
|
||||||
foundindexDataMap = make(map[string]mTypes.IndexData)
|
|
||||||
)
|
|
||||||
|
|
||||||
// keep just the manifestMeta we need
|
|
||||||
for _, repoMeta := range foundRepos {
|
|
||||||
for _, descriptor := range repoMeta.Tags {
|
|
||||||
switch descriptor.MediaType {
|
|
||||||
case ispec.MediaTypeImageManifest:
|
case ispec.MediaTypeImageManifest:
|
||||||
foundManifestMetadataMap[descriptor.Digest] = manifestMetadataMap[descriptor.Digest]
|
manifestData := imageMeta.Manifests[0]
|
||||||
|
|
||||||
|
vendor := GetVendor(manifestData.Manifest.Annotations)
|
||||||
|
if vendor == "" {
|
||||||
|
vendor = GetVendor(manifestData.Manifest.Annotations)
|
||||||
|
}
|
||||||
|
|
||||||
|
vendors := []string{}
|
||||||
|
if vendor != "" {
|
||||||
|
vendors = append(vendors, vendor)
|
||||||
|
}
|
||||||
|
|
||||||
|
platforms := []*proto_go.Platform{getProtoPlatform(&manifestData.Config.Platform)}
|
||||||
|
if platforms[0].OS == "" && platforms[0].Architecture == "" {
|
||||||
|
platforms = []*proto_go.Platform{}
|
||||||
|
}
|
||||||
|
|
||||||
|
subBlobs := []string{manifestData.Manifest.Config.Digest.String()}
|
||||||
|
repoBlobs.Blobs[manifestData.Manifest.Config.Digest.String()] = &proto_go.BlobInfo{
|
||||||
|
Size: manifestData.Manifest.Config.Size,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, layer := range manifestData.Manifest.Layers {
|
||||||
|
subBlobs = append(subBlobs, layer.Digest.String())
|
||||||
|
repoBlobs.Blobs[layer.Digest.String()] = &proto_go.BlobInfo{Size: layer.Size}
|
||||||
|
}
|
||||||
|
|
||||||
|
lastUpdated := zcommon.GetImageLastUpdated(manifestData.Config)
|
||||||
|
|
||||||
|
repoBlobs.Blobs[imageMeta.Digest.String()] = &proto_go.BlobInfo{
|
||||||
|
Size: imageMeta.Size,
|
||||||
|
Vendors: vendors,
|
||||||
|
Platforms: platforms,
|
||||||
|
SubBlobs: subBlobs,
|
||||||
|
LastUpdated: mConvert.GetProtoTime(&lastUpdated),
|
||||||
|
}
|
||||||
case ispec.MediaTypeImageIndex:
|
case ispec.MediaTypeImageIndex:
|
||||||
indexData := indexDataMap[descriptor.Digest]
|
subBlobs := []string{}
|
||||||
|
for _, manifest := range imageMeta.Index.Manifests {
|
||||||
var indexContent ispec.Index
|
subBlobs = append(subBlobs, manifest.Digest.String())
|
||||||
|
|
||||||
err := json.Unmarshal(indexData.IndexBlob, &indexContent)
|
|
||||||
if err != nil {
|
|
||||||
return map[string]mTypes.ManifestMetadata{}, map[string]mTypes.IndexData{},
|
|
||||||
fmt.Errorf("metadb: error while getting manifest data for digest %s %w", descriptor.Digest, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, manifestDescriptor := range indexContent.Manifests {
|
repoBlobs.Blobs[imageMeta.Digest.String()] = &proto_go.BlobInfo{
|
||||||
manifestDigest := manifestDescriptor.Digest.String()
|
Size: imageMeta.Size,
|
||||||
|
SubBlobs: subBlobs,
|
||||||
foundManifestMetadataMap[manifestDigest] = manifestMetadataMap[manifestDigest]
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foundindexDataMap[descriptor.Digest] = indexData
|
// update info only when a tag is added
|
||||||
default:
|
if zcommon.IsDigest(reference) {
|
||||||
|
return repoMeta, repoBlobs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
size, platforms, vendors := recalculateAggregateFields(repoMeta, repoBlobs)
|
||||||
|
repoMeta.Vendors = vendors
|
||||||
|
repoMeta.Platforms = platforms
|
||||||
|
repoMeta.Size = int32(size)
|
||||||
|
|
||||||
|
imageBlobInfo := repoBlobs.Blobs[imageMeta.Digest.String()]
|
||||||
|
repoMeta.LastUpdatedImage = mConvert.GetProtoEarlierUpdatedImage(repoMeta.LastUpdatedImage,
|
||||||
|
&proto_go.RepoLastUpdatedImage{
|
||||||
|
LastUpdated: imageBlobInfo.LastUpdated,
|
||||||
|
MediaType: imageMeta.MediaType,
|
||||||
|
Digest: imageMeta.Digest.String(),
|
||||||
|
Tag: reference,
|
||||||
|
})
|
||||||
|
|
||||||
|
return repoMeta, repoBlobs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RemoveImageFromRepoMeta(repoMeta *proto_go.RepoMeta, repoBlobs *proto_go.RepoBlobs, ref string,
|
||||||
|
) (*proto_go.RepoMeta, *proto_go.RepoBlobs, error) {
|
||||||
|
var updatedLastImage *proto_go.RepoLastUpdatedImage
|
||||||
|
|
||||||
|
updatedBlobs := map[string]*proto_go.BlobInfo{}
|
||||||
|
updatedSize := int64(0)
|
||||||
|
updatedVendors := []string{}
|
||||||
|
updatedPlatforms := []*proto_go.Platform{}
|
||||||
|
|
||||||
|
for tag, descriptor := range repoMeta.Tags {
|
||||||
|
if descriptor.Digest == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
queue := []string{descriptor.Digest}
|
||||||
|
|
||||||
|
mConvert.GetProtoEarlierUpdatedImage(updatedLastImage, &proto_go.RepoLastUpdatedImage{
|
||||||
|
LastUpdated: repoBlobs.Blobs[descriptor.Digest].LastUpdated,
|
||||||
|
MediaType: descriptor.MediaType,
|
||||||
|
Digest: descriptor.Digest,
|
||||||
|
Tag: tag,
|
||||||
|
})
|
||||||
|
|
||||||
|
for len(queue) > 0 {
|
||||||
|
currentBlob := queue[0]
|
||||||
|
queue = queue[1:]
|
||||||
|
|
||||||
|
if _, found := updatedBlobs[currentBlob]; !found {
|
||||||
|
blobInfo := repoBlobs.Blobs[currentBlob]
|
||||||
|
|
||||||
|
updatedBlobs[currentBlob] = blobInfo
|
||||||
|
updatedSize += blobInfo.Size
|
||||||
|
updatedVendors = mConvert.AddVendors(updatedVendors, blobInfo.Vendors)
|
||||||
|
updatedPlatforms = mConvert.AddProtoPlatforms(updatedPlatforms, blobInfo.Platforms)
|
||||||
|
|
||||||
|
queue = append(queue, blobInfo.SubBlobs...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return foundManifestMetadataMap, foundindexDataMap, nil
|
repoMeta.Size = int32(updatedSize)
|
||||||
|
repoMeta.Vendors = updatedVendors
|
||||||
|
repoMeta.Platforms = updatedPlatforms
|
||||||
|
repoMeta.LastUpdatedImage = updatedLastImage
|
||||||
|
|
||||||
|
repoBlobs.Blobs = updatedBlobs
|
||||||
|
|
||||||
|
return repoMeta, repoBlobs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func FetchDataForRepos(metaDB mTypes.MetaDB, foundRepos []mTypes.RepoMetadata,
|
func recalculateAggregateFields(repoMeta *proto_go.RepoMeta, repoBlobs *proto_go.RepoBlobs,
|
||||||
) (map[string]mTypes.ManifestMetadata, map[string]mTypes.IndexData, error) {
|
) (int64, []*proto_go.Platform, []string) {
|
||||||
foundManifestMetadataMap := map[string]mTypes.ManifestMetadata{}
|
size := int64(0)
|
||||||
foundIndexDataMap := map[string]mTypes.IndexData{}
|
platforms := []*proto_go.Platform{}
|
||||||
|
vendors := []string{}
|
||||||
|
blobsMap := map[string]struct{}{}
|
||||||
|
|
||||||
for idx := range foundRepos {
|
for _, descriptor := range repoMeta.Tags {
|
||||||
for _, descriptor := range foundRepos[idx].Tags {
|
if descriptor.Digest == "" {
|
||||||
switch descriptor.MediaType {
|
continue
|
||||||
case ispec.MediaTypeImageManifest:
|
|
||||||
manifestData, err := metaDB.GetManifestData(godigest.Digest(descriptor.Digest))
|
|
||||||
if err != nil {
|
|
||||||
return map[string]mTypes.ManifestMetadata{}, map[string]mTypes.IndexData{}, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foundManifestMetadataMap[descriptor.Digest] = mTypes.ManifestMetadata{
|
queue := []string{descriptor.Digest}
|
||||||
ManifestBlob: manifestData.ManifestBlob,
|
|
||||||
ConfigBlob: manifestData.ConfigBlob,
|
for len(queue) > 0 {
|
||||||
}
|
currentBlob := queue[0]
|
||||||
case ispec.MediaTypeImageIndex:
|
queue = queue[1:]
|
||||||
indexData, err := metaDB.GetIndexData(godigest.Digest(descriptor.Digest))
|
|
||||||
if err != nil {
|
if _, found := blobsMap[currentBlob]; !found {
|
||||||
return map[string]mTypes.ManifestMetadata{}, map[string]mTypes.IndexData{}, err
|
blobInfo := repoBlobs.Blobs[currentBlob]
|
||||||
|
if blobInfo == nil {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var indexContent ispec.Index
|
blobsMap[currentBlob] = struct{}{}
|
||||||
|
size += blobInfo.Size
|
||||||
|
vendors = mConvert.AddVendors(vendors, blobInfo.Vendors)
|
||||||
|
platforms = mConvert.AddProtoPlatforms(platforms, blobInfo.Platforms)
|
||||||
|
|
||||||
err = json.Unmarshal(indexData.IndexBlob, &indexContent)
|
queue = append(queue, blobInfo.SubBlobs...)
|
||||||
if err != nil {
|
|
||||||
return map[string]mTypes.ManifestMetadata{},
|
|
||||||
map[string]mTypes.IndexData{},
|
|
||||||
fmt.Errorf("metadb: error while getting index data for digest %s %w", descriptor.Digest, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, manifestDescriptor := range indexContent.Manifests {
|
|
||||||
manifestDigest := manifestDescriptor.Digest.String()
|
|
||||||
|
|
||||||
manifestData, err := metaDB.GetManifestData(manifestDescriptor.Digest)
|
|
||||||
if err != nil {
|
|
||||||
return map[string]mTypes.ManifestMetadata{}, map[string]mTypes.IndexData{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
foundManifestMetadataMap[manifestDigest] = mTypes.ManifestMetadata{
|
|
||||||
ManifestBlob: manifestData.ManifestBlob,
|
|
||||||
ConfigBlob: manifestData.ConfigBlob,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foundIndexDataMap[descriptor.Digest] = indexData
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return foundManifestMetadataMap, foundIndexDataMap, nil
|
return size, platforms, vendors
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindMediaTypeForDigest will look into the buckets for a certain digest. Depending on which bucket that
|
func getProtoPlatform(platform *ispec.Platform) *proto_go.Platform {
|
||||||
// digest is found the corresponding mediatype is returned.
|
if platform == nil {
|
||||||
func FindMediaTypeForDigest(metaDB mTypes.MetaDB, digest godigest.Digest) (bool, string) {
|
return nil
|
||||||
_, err := metaDB.GetManifestData(digest)
|
|
||||||
if err == nil {
|
|
||||||
return true, ispec.MediaTypeImageManifest
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = metaDB.GetIndexData(digest)
|
return &proto_go.Platform{
|
||||||
if err == nil {
|
Architecture: getArch(platform.Architecture, platform.Variant),
|
||||||
return true, ispec.MediaTypeImageIndex
|
OS: platform.OS,
|
||||||
}
|
}
|
||||||
|
|
||||||
return false, ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetImageDescriptor(metaDB mTypes.MetaDB, repo, tag string) (mTypes.Descriptor, error) {
|
func getArch(arch string, variant string) string {
|
||||||
repoMeta, err := metaDB.GetRepoMeta(repo)
|
if variant != "" {
|
||||||
if err != nil {
|
arch = arch + "/" + variant
|
||||||
return mTypes.Descriptor{}, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
imageDescriptor, ok := repoMeta.Tags[tag]
|
return arch
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetVendor(annotations map[string]string) string {
|
||||||
|
return GetAnnotationValue(annotations, ispec.AnnotationVendor, "org.label-schema.vendor")
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAnnotationValue(annotations map[string]string, annotationKey, labelKey string) string {
|
||||||
|
value, ok := annotations[annotationKey]
|
||||||
|
if !ok || value == "" {
|
||||||
|
value, ok = annotations[labelKey]
|
||||||
if !ok {
|
if !ok {
|
||||||
return mTypes.Descriptor{}, zerr.ErrTagMetaNotFound
|
value = ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return imageDescriptor, nil
|
return value
|
||||||
}
|
|
||||||
|
|
||||||
func InitializeImageConfig(blob []byte) ispec.Image {
|
|
||||||
var configContent ispec.Image
|
|
||||||
|
|
||||||
err := json.Unmarshal(blob, &configContent)
|
|
||||||
if err != nil {
|
|
||||||
return ispec.Image{}
|
|
||||||
}
|
|
||||||
|
|
||||||
return configContent
|
|
||||||
}
|
}
|
||||||
|
@ -5,23 +5,15 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/opencontainers/go-digest"
|
|
||||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
|
||||||
"zotregistry.io/zot/pkg/meta/common"
|
"zotregistry.io/zot/pkg/meta/common"
|
||||||
mTypes "zotregistry.io/zot/pkg/meta/types"
|
mTypes "zotregistry.io/zot/pkg/meta/types"
|
||||||
"zotregistry.io/zot/pkg/test/mocks"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrTestError = errors.New("test error")
|
var ErrTestError = errors.New("test error")
|
||||||
|
|
||||||
func TestUtils(t *testing.T) {
|
func TestUtils(t *testing.T) {
|
||||||
Convey("GetReferredSubject", t, func() {
|
|
||||||
_, err := common.GetReferredSubject([]byte("bad json"))
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("MatchesArtifactTypes", t, func() {
|
Convey("MatchesArtifactTypes", t, func() {
|
||||||
res := common.MatchesArtifactTypes("", nil)
|
res := common.MatchesArtifactTypes("", nil)
|
||||||
So(res, ShouldBeTrue)
|
So(res, ShouldBeTrue)
|
||||||
@ -116,145 +108,4 @@ func TestUtils(t *testing.T) {
|
|||||||
|
|
||||||
So(res, ShouldEqual, false)
|
So(res, ShouldEqual, false)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("FilterDataByRepo", t, func() {
|
|
||||||
Convey("Functionality", func() {
|
|
||||||
_, _, err := common.FilterDataByRepo(
|
|
||||||
[]mTypes.RepoMetadata{{
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"manifest": {
|
|
||||||
Digest: "manifestDigest",
|
|
||||||
MediaType: ispec.MediaTypeImageManifest,
|
|
||||||
},
|
|
||||||
"index": {
|
|
||||||
Digest: "indexDigest",
|
|
||||||
MediaType: ispec.MediaTypeImageIndex,
|
|
||||||
},
|
|
||||||
"rand": {
|
|
||||||
Digest: "randDigest",
|
|
||||||
MediaType: "rand",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
map[string]mTypes.ManifestMetadata{},
|
|
||||||
map[string]mTypes.IndexData{
|
|
||||||
"indexDigest": {
|
|
||||||
IndexBlob: []byte(`{
|
|
||||||
"manifests": [
|
|
||||||
{
|
|
||||||
"digest": "manifestDigest"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}`),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
Convey("Errors", func() {
|
|
||||||
// Unmarshal index data error
|
|
||||||
_, _, err := common.FilterDataByRepo(
|
|
||||||
[]mTypes.RepoMetadata{{
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"tag": {
|
|
||||||
Digest: "indexDigest",
|
|
||||||
MediaType: ispec.MediaTypeImageIndex,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
map[string]mTypes.ManifestMetadata{},
|
|
||||||
map[string]mTypes.IndexData{
|
|
||||||
"indexDigest": {
|
|
||||||
IndexBlob: []byte("bad blob"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("FetchDataForRepos", t, func() {
|
|
||||||
Convey("Errors", func() {
|
|
||||||
// Unmarshal index data error
|
|
||||||
_, _, err := common.FetchDataForRepos(
|
|
||||||
mocks.MetaDBMock{
|
|
||||||
GetIndexDataFn: func(indexDigest digest.Digest) (mTypes.IndexData, error) {
|
|
||||||
return mTypes.IndexData{
|
|
||||||
IndexBlob: []byte("bad blob"),
|
|
||||||
}, nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
[]mTypes.RepoMetadata{{
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"tag": {
|
|
||||||
Digest: "indexDigest",
|
|
||||||
MediaType: ispec.MediaTypeImageIndex,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFetchDataForRepos(t *testing.T) {
|
|
||||||
Convey("GetReferredSubject", t, func() {
|
|
||||||
mockMetaDB := mocks.MetaDBMock{}
|
|
||||||
|
|
||||||
Convey("GetManifestData errors", func() {
|
|
||||||
mockMetaDB.GetManifestDataFn = func(manifestDigest digest.Digest) (mTypes.ManifestData, error) {
|
|
||||||
return mTypes.ManifestData{}, ErrTestError
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _, err := common.FetchDataForRepos(mockMetaDB, []mTypes.RepoMetadata{
|
|
||||||
{
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"tag1": {Digest: "dig1", MediaType: ispec.MediaTypeImageManifest},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetIndexData errors", func() {
|
|
||||||
mockMetaDB.GetIndexDataFn = func(indexDigest digest.Digest) (mTypes.IndexData, error) {
|
|
||||||
return mTypes.IndexData{}, ErrTestError
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _, err := common.FetchDataForRepos(mockMetaDB, []mTypes.RepoMetadata{
|
|
||||||
{
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"tag1": {Digest: "dig1", MediaType: ispec.MediaTypeImageIndex},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetIndexData ok, GetManifestData errors", func() {
|
|
||||||
mockMetaDB.GetIndexDataFn = func(indexDigest digest.Digest) (mTypes.IndexData, error) {
|
|
||||||
return mTypes.IndexData{
|
|
||||||
IndexBlob: []byte(`{
|
|
||||||
"manifests": [
|
|
||||||
{"digest": "dig1"}
|
|
||||||
]
|
|
||||||
}`),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
mockMetaDB.GetManifestDataFn = func(manifestDigest digest.Digest) (mTypes.ManifestData, error) {
|
|
||||||
return mTypes.ManifestData{}, ErrTestError
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _, err := common.FetchDataForRepos(mockMetaDB, []mTypes.RepoMetadata{
|
|
||||||
{
|
|
||||||
Tags: map[string]mTypes.Descriptor{
|
|
||||||
"tag1": {Digest: "dig1", MediaType: ispec.MediaTypeImageIndex},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
611
pkg/meta/convert/convert.go
Normal file
611
pkg/meta/convert/convert.go
Normal file
@ -0,0 +1,611 @@
|
|||||||
|
package convert
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
godigest "github.com/opencontainers/go-digest"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
|
||||||
|
"zotregistry.io/zot/pkg/common"
|
||||||
|
proto_go "zotregistry.io/zot/pkg/meta/proto/gen"
|
||||||
|
mTypes "zotregistry.io/zot/pkg/meta/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetHistory(history []*proto_go.History) []ispec.History {
|
||||||
|
if history == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
results := make([]ispec.History, 0, len(history))
|
||||||
|
|
||||||
|
for _, his := range history {
|
||||||
|
results = append(results, ispec.History{
|
||||||
|
Created: ref(his.Created.AsTime()),
|
||||||
|
CreatedBy: deref(his.CreatedBy, ""),
|
||||||
|
Author: deref(his.Author, ""),
|
||||||
|
Comment: deref(his.Comment, ""),
|
||||||
|
EmptyLayer: deref(his.EmptyLayer, false),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetImageArtifactType(imageMeta *proto_go.ImageMeta) string {
|
||||||
|
switch imageMeta.MediaType {
|
||||||
|
case ispec.MediaTypeImageManifest:
|
||||||
|
manifestArtifactType := deref(imageMeta.Manifests[0].Manifest.ArtifactType, "")
|
||||||
|
if manifestArtifactType != "" {
|
||||||
|
return manifestArtifactType
|
||||||
|
}
|
||||||
|
|
||||||
|
return imageMeta.Manifests[0].Manifest.Config.MediaType
|
||||||
|
case ispec.MediaTypeImageIndex:
|
||||||
|
return deref(imageMeta.Index.Index.ArtifactType, "")
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetImageManifestSize(imageMeta *proto_go.ImageMeta) int64 {
|
||||||
|
switch imageMeta.MediaType {
|
||||||
|
case ispec.MediaTypeImageManifest:
|
||||||
|
return imageMeta.Manifests[0].Size
|
||||||
|
case ispec.MediaTypeImageIndex:
|
||||||
|
return imageMeta.Index.Size
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetImageDigest(imageMeta *proto_go.ImageMeta) godigest.Digest {
|
||||||
|
switch imageMeta.MediaType {
|
||||||
|
case ispec.MediaTypeImageManifest:
|
||||||
|
return godigest.Digest(imageMeta.Manifests[0].Digest)
|
||||||
|
case ispec.MediaTypeImageIndex:
|
||||||
|
return godigest.Digest(imageMeta.Index.Digest)
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetImageDigestStr(imageMeta *proto_go.ImageMeta) string {
|
||||||
|
switch imageMeta.MediaType {
|
||||||
|
case ispec.MediaTypeImageManifest:
|
||||||
|
return imageMeta.Manifests[0].Digest
|
||||||
|
case ispec.MediaTypeImageIndex:
|
||||||
|
return imageMeta.Index.Digest
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetImageAnnotations(imageMeta *proto_go.ImageMeta) map[string]string {
|
||||||
|
switch imageMeta.MediaType {
|
||||||
|
case ispec.MediaTypeImageManifest:
|
||||||
|
return imageMeta.Manifests[0].Manifest.Annotations
|
||||||
|
case ispec.MediaTypeImageIndex:
|
||||||
|
return imageMeta.Index.Index.Annotations
|
||||||
|
default:
|
||||||
|
return map[string]string{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetImageSubject(imageMeta *proto_go.ImageMeta) *ispec.Descriptor {
|
||||||
|
switch imageMeta.MediaType {
|
||||||
|
case ispec.MediaTypeImageManifest:
|
||||||
|
if imageMeta.Manifests[0].Manifest.Subject == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetDescriptorRef(imageMeta.Manifests[0].Manifest.Subject)
|
||||||
|
case ispec.MediaTypeImageIndex:
|
||||||
|
if imageMeta.Index.Index.Subject == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetDescriptorRef(imageMeta.Index.Index.Subject)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDescriptorRef(descriptor *proto_go.Descriptor) *ispec.Descriptor {
|
||||||
|
if descriptor == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
platform := GetPlatformRef(descriptor.Platform)
|
||||||
|
|
||||||
|
return &ispec.Descriptor{
|
||||||
|
MediaType: descriptor.MediaType,
|
||||||
|
Digest: godigest.Digest(descriptor.Digest),
|
||||||
|
Size: descriptor.Size,
|
||||||
|
URLs: descriptor.URLs,
|
||||||
|
Data: descriptor.Data,
|
||||||
|
Platform: platform,
|
||||||
|
ArtifactType: deref(descriptor.ArtifactType, ""),
|
||||||
|
Annotations: descriptor.Annotations,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPlatform(platform *proto_go.Platform) ispec.Platform {
|
||||||
|
if platform == nil {
|
||||||
|
return ispec.Platform{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ispec.Platform{
|
||||||
|
Architecture: platform.Architecture,
|
||||||
|
OS: platform.OS,
|
||||||
|
OSVersion: deref(platform.OSVersion, ""),
|
||||||
|
OSFeatures: platform.OSFeatures,
|
||||||
|
Variant: deref(platform.Variant, ""),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPlatformRef(platform *proto_go.Platform) *ispec.Platform {
|
||||||
|
if platform == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ispec.Platform{
|
||||||
|
Architecture: platform.Architecture,
|
||||||
|
OS: platform.OS,
|
||||||
|
OSVersion: deref(platform.OSVersion, ""),
|
||||||
|
OSFeatures: platform.OSFeatures,
|
||||||
|
Variant: deref(platform.Variant, ""),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLayers(descriptors []*proto_go.Descriptor) []ispec.Descriptor {
|
||||||
|
results := make([]ispec.Descriptor, 0, len(descriptors))
|
||||||
|
|
||||||
|
for _, desc := range descriptors {
|
||||||
|
results = append(results, ispec.Descriptor{
|
||||||
|
MediaType: desc.MediaType,
|
||||||
|
Digest: godigest.Digest(desc.Digest),
|
||||||
|
Size: desc.Size,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSubject(subj *proto_go.Descriptor) *ispec.Descriptor {
|
||||||
|
if subj == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ispec.Descriptor{
|
||||||
|
MediaType: subj.MediaType,
|
||||||
|
Digest: godigest.Digest(subj.Digest),
|
||||||
|
Size: subj.Size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetReferrers(refs map[string]*proto_go.ReferrersInfo) map[string][]mTypes.ReferrerInfo {
|
||||||
|
results := map[string][]mTypes.ReferrerInfo{}
|
||||||
|
|
||||||
|
for digest, ref := range refs {
|
||||||
|
referrers := []mTypes.ReferrerInfo{}
|
||||||
|
|
||||||
|
for _, dbRef := range ref.List {
|
||||||
|
referrers = append(referrers, mTypes.ReferrerInfo{
|
||||||
|
Digest: dbRef.Digest,
|
||||||
|
MediaType: dbRef.MediaType,
|
||||||
|
ArtifactType: dbRef.ArtifactType,
|
||||||
|
Size: int(dbRef.Size),
|
||||||
|
Annotations: dbRef.Annotations,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
results[digest] = referrers
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetImageReferrers(refs *proto_go.ReferrersInfo) []mTypes.ReferrerInfo {
|
||||||
|
if refs == nil {
|
||||||
|
return []mTypes.ReferrerInfo{}
|
||||||
|
}
|
||||||
|
|
||||||
|
results := []mTypes.ReferrerInfo{}
|
||||||
|
|
||||||
|
for _, dbRef := range refs.List {
|
||||||
|
results = append(results, mTypes.ReferrerInfo{
|
||||||
|
Digest: dbRef.Digest,
|
||||||
|
MediaType: dbRef.MediaType,
|
||||||
|
ArtifactType: dbRef.ArtifactType,
|
||||||
|
Size: int(dbRef.Size),
|
||||||
|
Annotations: dbRef.Annotations,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSignatures(sigs map[string]*proto_go.ManifestSignatures) map[string]mTypes.ManifestSignatures {
|
||||||
|
results := map[string]mTypes.ManifestSignatures{}
|
||||||
|
|
||||||
|
for digest, dbSignatures := range sigs {
|
||||||
|
imageSignatures := mTypes.ManifestSignatures{}
|
||||||
|
|
||||||
|
for signatureName, signatureInfo := range dbSignatures.Map {
|
||||||
|
imageSignatures[signatureName] = GetSignaturesInfo(signatureInfo.List)
|
||||||
|
}
|
||||||
|
|
||||||
|
results[digest] = imageSignatures
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetImageSignatures(sigs *proto_go.ManifestSignatures) mTypes.ManifestSignatures {
|
||||||
|
if sigs == nil {
|
||||||
|
return mTypes.ManifestSignatures{}
|
||||||
|
}
|
||||||
|
|
||||||
|
results := mTypes.ManifestSignatures{}
|
||||||
|
|
||||||
|
for signatureName, signatureInfo := range sigs.Map {
|
||||||
|
results[signatureName] = GetSignaturesInfo(signatureInfo.List)
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSignaturesInfo(sigsInfo []*proto_go.SignatureInfo) []mTypes.SignatureInfo {
|
||||||
|
results := []mTypes.SignatureInfo{}
|
||||||
|
|
||||||
|
for _, siginfo := range sigsInfo {
|
||||||
|
results = append(results, mTypes.SignatureInfo{
|
||||||
|
SignatureManifestDigest: siginfo.SignatureManifestDigest,
|
||||||
|
LayersInfo: GetLayersInfo(siginfo.LayersInfo),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLayersInfo(layersInfo []*proto_go.LayersInfo) []mTypes.LayerInfo {
|
||||||
|
results := []mTypes.LayerInfo{}
|
||||||
|
|
||||||
|
for _, layerInfo := range layersInfo {
|
||||||
|
date := time.Time{}
|
||||||
|
|
||||||
|
if layerInfo.Date != nil {
|
||||||
|
date = layerInfo.Date.AsTime()
|
||||||
|
}
|
||||||
|
|
||||||
|
results = append(results, mTypes.LayerInfo{
|
||||||
|
LayerDigest: layerInfo.LayerDigest,
|
||||||
|
LayerContent: layerInfo.LayerContent,
|
||||||
|
SignatureKey: layerInfo.SignatureKey,
|
||||||
|
Signer: layerInfo.Signer,
|
||||||
|
Date: date,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetStatisticsMap(stats map[string]*proto_go.DescriptorStatistics) map[string]mTypes.DescriptorStatistics {
|
||||||
|
results := map[string]mTypes.DescriptorStatistics{}
|
||||||
|
|
||||||
|
for digest, stat := range stats {
|
||||||
|
results[digest] = mTypes.DescriptorStatistics{
|
||||||
|
DownloadCount: int(stat.DownloadCount),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetImageStatistics(stats *proto_go.DescriptorStatistics) mTypes.DescriptorStatistics {
|
||||||
|
if stats == nil {
|
||||||
|
return mTypes.DescriptorStatistics{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mTypes.DescriptorStatistics{
|
||||||
|
DownloadCount: int(stats.DownloadCount),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetImageManifestMeta(manifestContent ispec.Manifest, configContent ispec.Image, size int64,
|
||||||
|
digest godigest.Digest,
|
||||||
|
) mTypes.ImageMeta {
|
||||||
|
return mTypes.ImageMeta{
|
||||||
|
MediaType: ispec.MediaTypeImageManifest,
|
||||||
|
Digest: digest,
|
||||||
|
Size: size,
|
||||||
|
Manifests: []mTypes.ManifestData{
|
||||||
|
{
|
||||||
|
Digest: digest,
|
||||||
|
Size: size,
|
||||||
|
Config: configContent,
|
||||||
|
Manifest: manifestContent,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetImageIndexMeta(indexContent ispec.Index, size int64, digest godigest.Digest) mTypes.ImageMeta {
|
||||||
|
return mTypes.ImageMeta{
|
||||||
|
MediaType: ispec.MediaTypeImageIndex,
|
||||||
|
Index: &indexContent,
|
||||||
|
Manifests: GetManifests(indexContent.Manifests),
|
||||||
|
Size: size,
|
||||||
|
Digest: digest,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTags(tags map[string]*proto_go.TagDescriptor) map[string]mTypes.Descriptor {
|
||||||
|
resultMap := map[string]mTypes.Descriptor{}
|
||||||
|
|
||||||
|
for tag, tagDescriptor := range tags {
|
||||||
|
resultMap[tag] = mTypes.Descriptor{
|
||||||
|
Digest: tagDescriptor.Digest,
|
||||||
|
MediaType: tagDescriptor.MediaType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetManifests(descriptors []ispec.Descriptor) []mTypes.ManifestData {
|
||||||
|
manifestList := []mTypes.ManifestData{}
|
||||||
|
|
||||||
|
for _, manifest := range descriptors {
|
||||||
|
manifestList = append(manifestList, mTypes.ManifestData{
|
||||||
|
Digest: manifest.Digest,
|
||||||
|
Size: manifest.Size,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return manifestList
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTime(time *timestamppb.Timestamp) *time.Time {
|
||||||
|
if time == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return ref(time.AsTime())
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetFullImageMetaFromProto(tag string, protoRepoMeta *proto_go.RepoMeta, protoImageMeta *proto_go.ImageMeta,
|
||||||
|
) mTypes.FullImageMeta {
|
||||||
|
imageMeta := GetImageMeta(protoImageMeta)
|
||||||
|
imageDigest := imageMeta.Digest.String()
|
||||||
|
|
||||||
|
return mTypes.FullImageMeta{
|
||||||
|
Repo: protoRepoMeta.Name,
|
||||||
|
Tag: tag,
|
||||||
|
MediaType: imageMeta.MediaType,
|
||||||
|
Digest: imageMeta.Digest,
|
||||||
|
Size: imageMeta.Size,
|
||||||
|
Index: imageMeta.Index,
|
||||||
|
Manifests: GetFullManifestData(protoRepoMeta, imageMeta.Manifests),
|
||||||
|
IsStarred: protoRepoMeta.IsStarred,
|
||||||
|
IsBookmarked: protoRepoMeta.IsBookmarked,
|
||||||
|
|
||||||
|
Referrers: GetImageReferrers(protoRepoMeta.Referrers[imageDigest]),
|
||||||
|
Statistics: GetImageStatistics(protoRepoMeta.Statistics[imageDigest]),
|
||||||
|
Signatures: GetImageSignatures(protoRepoMeta.Signatures[imageDigest]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetFullManifestData(protoRepoMeta *proto_go.RepoMeta, manifestData []mTypes.ManifestData,
|
||||||
|
) []mTypes.FullManifestMeta {
|
||||||
|
results := []mTypes.FullManifestMeta{}
|
||||||
|
|
||||||
|
for i := range manifestData {
|
||||||
|
results = append(results, mTypes.FullManifestMeta{
|
||||||
|
ManifestData: manifestData[i],
|
||||||
|
Referrers: GetImageReferrers(protoRepoMeta.Referrers[manifestData[i].Digest.String()]),
|
||||||
|
Statistics: GetImageStatistics(protoRepoMeta.Statistics[manifestData[i].Digest.String()]),
|
||||||
|
Signatures: GetImageSignatures(protoRepoMeta.Signatures[manifestData[i].Digest.String()]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRepoMeta(protoRepoMeta *proto_go.RepoMeta) mTypes.RepoMeta {
|
||||||
|
repoDownloads := int32(0)
|
||||||
|
|
||||||
|
for _, descriptor := range protoRepoMeta.Tags {
|
||||||
|
if statistic := protoRepoMeta.Statistics[descriptor.Digest]; statistic != nil {
|
||||||
|
repoDownloads += statistic.DownloadCount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mTypes.RepoMeta{
|
||||||
|
Name: protoRepoMeta.Name,
|
||||||
|
Tags: GetTags(protoRepoMeta.Tags),
|
||||||
|
Rank: int(protoRepoMeta.Rank),
|
||||||
|
Size: int64(protoRepoMeta.Size),
|
||||||
|
Platforms: GetPlatforms(protoRepoMeta.Platforms),
|
||||||
|
Vendors: protoRepoMeta.Vendors,
|
||||||
|
IsStarred: protoRepoMeta.IsStarred,
|
||||||
|
IsBookmarked: protoRepoMeta.IsBookmarked,
|
||||||
|
StarCount: int(protoRepoMeta.Stars),
|
||||||
|
DownloadCount: int(repoDownloads),
|
||||||
|
LastUpdatedImage: GetLastUpdatedImage(protoRepoMeta.LastUpdatedImage),
|
||||||
|
Statistics: GetStatisticsMap(protoRepoMeta.Statistics),
|
||||||
|
Signatures: GetSignatures(protoRepoMeta.Signatures),
|
||||||
|
Referrers: GetReferrers(protoRepoMeta.Referrers),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPlatforms(platforms []*proto_go.Platform) []ispec.Platform {
|
||||||
|
result := []ispec.Platform{}
|
||||||
|
|
||||||
|
for i := range platforms {
|
||||||
|
result = append(result, GetPlatform(platforms[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddProtoPlatforms(platforms []*proto_go.Platform, newPlatforms []*proto_go.Platform) []*proto_go.Platform {
|
||||||
|
for _, newPlatform := range newPlatforms {
|
||||||
|
if !ContainsProtoPlatform(platforms, newPlatform) {
|
||||||
|
platforms = append(platforms, newPlatform)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return platforms
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContainsProtoPlatform(platforms []*proto_go.Platform, platform *proto_go.Platform) bool {
|
||||||
|
for i := range platforms {
|
||||||
|
if platforms[i].OS == platform.OS && platforms[i].Architecture == platform.Architecture {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddVendors(vendors []string, newVendors []string) []string {
|
||||||
|
for _, newVendor := range newVendors {
|
||||||
|
if !common.Contains(vendors, newVendor) {
|
||||||
|
vendors = append(vendors, newVendor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vendors
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLastUpdatedImage(protoLastUpdated *proto_go.RepoLastUpdatedImage) *mTypes.LastUpdatedImage {
|
||||||
|
if protoLastUpdated == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &mTypes.LastUpdatedImage{
|
||||||
|
Descriptor: mTypes.Descriptor{
|
||||||
|
Digest: protoLastUpdated.Digest,
|
||||||
|
MediaType: protoLastUpdated.MediaType,
|
||||||
|
},
|
||||||
|
Tag: protoLastUpdated.Tag,
|
||||||
|
LastUpdated: GetTime(protoLastUpdated.LastUpdated),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetImageMeta(dbImageMeta *proto_go.ImageMeta) mTypes.ImageMeta {
|
||||||
|
imageMeta := mTypes.ImageMeta{
|
||||||
|
MediaType: dbImageMeta.MediaType,
|
||||||
|
Size: GetImageManifestSize(dbImageMeta),
|
||||||
|
Digest: GetImageDigest(dbImageMeta),
|
||||||
|
}
|
||||||
|
|
||||||
|
if dbImageMeta.MediaType == ispec.MediaTypeImageIndex {
|
||||||
|
manifests := make([]ispec.Descriptor, 0, len(dbImageMeta.Manifests))
|
||||||
|
|
||||||
|
for _, manifest := range dbImageMeta.Manifests {
|
||||||
|
manifests = append(manifests, ispec.Descriptor{
|
||||||
|
MediaType: deref(manifest.Manifest.MediaType, ""),
|
||||||
|
Digest: godigest.Digest(manifest.Digest),
|
||||||
|
Size: manifest.Size,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
imageMeta.Index = &ispec.Index{
|
||||||
|
Versioned: specs.Versioned{SchemaVersion: int(dbImageMeta.Index.Index.Versioned.GetSchemaVersion())},
|
||||||
|
MediaType: ispec.MediaTypeImageIndex,
|
||||||
|
Manifests: manifests,
|
||||||
|
Subject: GetImageSubject(dbImageMeta),
|
||||||
|
ArtifactType: GetImageArtifactType(dbImageMeta),
|
||||||
|
Annotations: GetImageAnnotations(dbImageMeta),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
manifestDataList := make([]mTypes.ManifestData, 0, len(dbImageMeta.Manifests))
|
||||||
|
|
||||||
|
for _, manifest := range dbImageMeta.Manifests {
|
||||||
|
manifestDataList = append(manifestDataList, mTypes.ManifestData{
|
||||||
|
Size: manifest.Size,
|
||||||
|
Digest: godigest.Digest(manifest.Digest),
|
||||||
|
Manifest: ispec.Manifest{
|
||||||
|
Versioned: specs.Versioned{SchemaVersion: int(manifest.Manifest.Versioned.GetSchemaVersion())},
|
||||||
|
MediaType: deref(manifest.Manifest.MediaType, ""),
|
||||||
|
ArtifactType: deref(manifest.Manifest.ArtifactType, ""),
|
||||||
|
Config: ispec.Descriptor{
|
||||||
|
MediaType: manifest.Manifest.Config.MediaType,
|
||||||
|
Size: manifest.Manifest.Config.Size,
|
||||||
|
Digest: godigest.Digest(manifest.Manifest.Config.Digest),
|
||||||
|
},
|
||||||
|
Layers: GetLayers(manifest.Manifest.Layers),
|
||||||
|
Subject: GetSubject(manifest.Manifest.Subject),
|
||||||
|
Annotations: manifest.Manifest.Annotations,
|
||||||
|
},
|
||||||
|
Config: ispec.Image{
|
||||||
|
Created: GetTime(manifest.Config.Created),
|
||||||
|
Author: deref(manifest.Config.Author, ""),
|
||||||
|
Platform: GetPlatform(manifest.Config.Platform),
|
||||||
|
Config: ispec.ImageConfig{
|
||||||
|
User: manifest.Config.Config.User,
|
||||||
|
ExposedPorts: GetExposedPorts(manifest.Config.Config.ExposedPorts),
|
||||||
|
Env: manifest.Config.Config.Env,
|
||||||
|
Entrypoint: manifest.Config.Config.Entrypoint,
|
||||||
|
Cmd: manifest.Config.Config.Cmd,
|
||||||
|
Volumes: GetConfigVolumes(manifest.Config.Config.Volumes),
|
||||||
|
WorkingDir: deref(manifest.Config.Config.WorkingDir, ""),
|
||||||
|
Labels: manifest.Config.Config.Labels,
|
||||||
|
StopSignal: deref(manifest.Config.Config.StopSignal, ""),
|
||||||
|
},
|
||||||
|
RootFS: ispec.RootFS{
|
||||||
|
Type: manifest.Config.RootFS.Type,
|
||||||
|
DiffIDs: GetDiffIDs(manifest.Config.RootFS.DiffIDs),
|
||||||
|
},
|
||||||
|
History: GetHistory(manifest.Config.History),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
imageMeta.Manifests = manifestDataList
|
||||||
|
|
||||||
|
return imageMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetExposedPorts(exposedPorts map[string]*proto_go.EmptyMessage) map[string]struct{} {
|
||||||
|
if exposedPorts == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result := map[string]struct{}{}
|
||||||
|
|
||||||
|
for key := range exposedPorts {
|
||||||
|
result[key] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetConfigVolumes(configVolumes map[string]*proto_go.EmptyMessage) map[string]struct{} {
|
||||||
|
if configVolumes == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result := map[string]struct{}{}
|
||||||
|
|
||||||
|
for key := range configVolumes {
|
||||||
|
result[key] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDiffIDs(diffIDs []string) []godigest.Digest {
|
||||||
|
result := make([]godigest.Digest, 0, len(diffIDs))
|
||||||
|
|
||||||
|
for i := range diffIDs {
|
||||||
|
result = append(result, godigest.Digest(diffIDs[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
392
pkg/meta/convert/convert_proto.go
Normal file
392
pkg/meta/convert/convert_proto.go
Normal file
@ -0,0 +1,392 @@
|
|||||||
|
package convert
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
godigest "github.com/opencontainers/go-digest"
|
||||||
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
|
||||||
|
"zotregistry.io/zot/pkg/common"
|
||||||
|
proto_go "zotregistry.io/zot/pkg/meta/proto/gen"
|
||||||
|
mTypes "zotregistry.io/zot/pkg/meta/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetProtoRepoMeta(repo mTypes.RepoMeta) *proto_go.RepoMeta {
|
||||||
|
return &proto_go.RepoMeta{
|
||||||
|
Name: repo.Name,
|
||||||
|
Tags: GetProtoTags(repo.Tags),
|
||||||
|
Statistics: GetProtoStatistics(repo.Statistics),
|
||||||
|
Signatures: GetProtoSignatures(repo.Signatures),
|
||||||
|
Referrers: GetProtoReferrers(repo.Referrers),
|
||||||
|
Size: int32(repo.Size),
|
||||||
|
Vendors: repo.Vendors,
|
||||||
|
Platforms: GetProtoPlatforms(repo.Platforms),
|
||||||
|
LastUpdatedImage: GetProtoLastUpdatedImage(repo.LastUpdatedImage),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProtoImageMeta(imageMeta mTypes.ImageMeta) *proto_go.ImageMeta {
|
||||||
|
switch imageMeta.MediaType {
|
||||||
|
case ispec.MediaTypeImageManifest:
|
||||||
|
if len(imageMeta.Manifests) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
manifestData := imageMeta.Manifests[0]
|
||||||
|
|
||||||
|
return GetProtoImageManifestData(manifestData.Manifest, manifestData.Config, manifestData.Size,
|
||||||
|
manifestData.Digest.String())
|
||||||
|
case ispec.MediaTypeImageIndex:
|
||||||
|
if imageMeta.Index == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetProtoImageIndexMeta(*imageMeta.Index, imageMeta.Size, imageMeta.Digest.String())
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProtoImageManifestData(manifestContent ispec.Manifest, configContent ispec.Image, size int64, digest string,
|
||||||
|
) *proto_go.ImageMeta {
|
||||||
|
return &proto_go.ImageMeta{
|
||||||
|
MediaType: ispec.MediaTypeImageManifest,
|
||||||
|
Manifests: []*proto_go.ManifestMeta{GetProtoManifestMeta(manifestContent, configContent, size, digest)},
|
||||||
|
Index: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProtoManifestMeta(manifestContent ispec.Manifest, configContent ispec.Image, size int64, digest string,
|
||||||
|
) *proto_go.ManifestMeta {
|
||||||
|
return &proto_go.ManifestMeta{
|
||||||
|
Digest: digest,
|
||||||
|
Size: size,
|
||||||
|
Manifest: &proto_go.Manifest{
|
||||||
|
Versioned: &proto_go.Versioned{SchemaVersion: int32(manifestContent.SchemaVersion)},
|
||||||
|
Config: &proto_go.Descriptor{
|
||||||
|
Digest: manifestContent.Config.Digest.String(),
|
||||||
|
Size: manifestContent.Config.Size,
|
||||||
|
MediaType: manifestContent.Config.MediaType,
|
||||||
|
},
|
||||||
|
MediaType: ref(ispec.MediaTypeImageManifest),
|
||||||
|
ArtifactType: &manifestContent.ArtifactType,
|
||||||
|
Layers: getProtoManifestLayers(manifestContent.Layers),
|
||||||
|
Subject: getProtoDesc(manifestContent.Subject),
|
||||||
|
Annotations: manifestContent.Annotations,
|
||||||
|
},
|
||||||
|
Config: &proto_go.Image{
|
||||||
|
Created: GetProtoTime(configContent.Created),
|
||||||
|
Author: &configContent.Author,
|
||||||
|
Platform: GetProtoPlatform(&configContent.Platform),
|
||||||
|
Config: &proto_go.ImageConfig{
|
||||||
|
User: configContent.Config.User,
|
||||||
|
ExposedPorts: getProtoExposedPorts(configContent.Config.ExposedPorts),
|
||||||
|
Env: configContent.Config.Env,
|
||||||
|
Entrypoint: configContent.Config.Entrypoint,
|
||||||
|
Cmd: configContent.Config.Cmd,
|
||||||
|
Volumes: getProtoConfigVolumes(configContent.Config.Volumes),
|
||||||
|
WorkingDir: &configContent.Config.WorkingDir,
|
||||||
|
Labels: configContent.Config.Labels,
|
||||||
|
StopSignal: &configContent.Config.StopSignal,
|
||||||
|
},
|
||||||
|
RootFS: &proto_go.RootFS{
|
||||||
|
Type: configContent.RootFS.Type,
|
||||||
|
DiffIDs: getProtoDiffIDs(configContent.RootFS.DiffIDs),
|
||||||
|
},
|
||||||
|
History: getProtoHistory(configContent.History),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProtoImageIndexMeta(indexContent ispec.Index, size int64, digest string) *proto_go.ImageMeta {
|
||||||
|
return &proto_go.ImageMeta{
|
||||||
|
MediaType: ispec.MediaTypeImageIndex,
|
||||||
|
Index: &proto_go.IndexMeta{
|
||||||
|
Size: size,
|
||||||
|
Digest: digest,
|
||||||
|
Index: &proto_go.Index{
|
||||||
|
Versioned: &proto_go.Versioned{SchemaVersion: int32(indexContent.Versioned.SchemaVersion)},
|
||||||
|
MediaType: ref(ispec.MediaTypeImageIndex),
|
||||||
|
ArtifactType: ref(common.GetIndexArtifactType(indexContent)),
|
||||||
|
Manifests: getProtoManifestList(indexContent.Manifests),
|
||||||
|
Subject: getProtoDesc(indexContent.Subject),
|
||||||
|
Annotations: indexContent.Annotations,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProtoStatistics(stats map[string]mTypes.DescriptorStatistics) map[string]*proto_go.DescriptorStatistics {
|
||||||
|
results := map[string]*proto_go.DescriptorStatistics{}
|
||||||
|
|
||||||
|
for digest, stat := range stats {
|
||||||
|
results[digest] = &proto_go.DescriptorStatistics{
|
||||||
|
DownloadCount: int32(stat.DownloadCount),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProtoPlatforms(platforms []ispec.Platform) []*proto_go.Platform {
|
||||||
|
result := []*proto_go.Platform{}
|
||||||
|
|
||||||
|
for i := range platforms {
|
||||||
|
result = append(result, &proto_go.Platform{
|
||||||
|
OS: platforms[i].OS,
|
||||||
|
Architecture: platforms[i].Architecture,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProtoReferrers(refs map[string][]mTypes.ReferrerInfo) map[string]*proto_go.ReferrersInfo {
|
||||||
|
results := map[string]*proto_go.ReferrersInfo{}
|
||||||
|
|
||||||
|
for digest, ref := range refs {
|
||||||
|
referrersInfoList := []*proto_go.ReferrerInfo{}
|
||||||
|
|
||||||
|
for _, dbRef := range ref {
|
||||||
|
referrersInfoList = append(referrersInfoList, GetProtoReferrerInfo(dbRef))
|
||||||
|
}
|
||||||
|
|
||||||
|
results[digest] = &proto_go.ReferrersInfo{List: referrersInfoList}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProtoSignatures(sigs map[string]mTypes.ManifestSignatures) map[string]*proto_go.ManifestSignatures {
|
||||||
|
results := map[string]*proto_go.ManifestSignatures{}
|
||||||
|
|
||||||
|
for digest, dbSignatures := range sigs {
|
||||||
|
imageSignatures := &proto_go.ManifestSignatures{Map: map[string]*proto_go.SignaturesInfo{}}
|
||||||
|
|
||||||
|
for signatureName, signatureInfo := range dbSignatures {
|
||||||
|
imageSignatures.Map[signatureName] = &proto_go.SignaturesInfo{List: GetProtoSignaturesInfo(signatureInfo)}
|
||||||
|
}
|
||||||
|
|
||||||
|
results[digest] = imageSignatures
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProtoSignaturesInfo(sigsInfo []mTypes.SignatureInfo) []*proto_go.SignatureInfo {
|
||||||
|
results := []*proto_go.SignatureInfo{}
|
||||||
|
|
||||||
|
for _, sigInfo := range sigsInfo {
|
||||||
|
results = append(results, &proto_go.SignatureInfo{
|
||||||
|
SignatureManifestDigest: sigInfo.SignatureManifestDigest,
|
||||||
|
LayersInfo: GetProtoLayersInfo(sigInfo.LayersInfo),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProtoLayersInfo(layersInfo []mTypes.LayerInfo) []*proto_go.LayersInfo {
|
||||||
|
result := make([]*proto_go.LayersInfo, 0, len(layersInfo))
|
||||||
|
|
||||||
|
for _, layerInfo := range layersInfo {
|
||||||
|
result = append(result, &proto_go.LayersInfo{
|
||||||
|
LayerDigest: layerInfo.LayerDigest,
|
||||||
|
LayerContent: layerInfo.LayerContent,
|
||||||
|
SignatureKey: layerInfo.SignatureKey,
|
||||||
|
Signer: layerInfo.Signer,
|
||||||
|
Date: timestamppb.New(layerInfo.Date),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func getProtoManifestLayers(layers []ispec.Descriptor) []*proto_go.Descriptor {
|
||||||
|
protoLayers := []*proto_go.Descriptor{}
|
||||||
|
|
||||||
|
for _, layer := range layers {
|
||||||
|
layer := layer
|
||||||
|
|
||||||
|
protoLayers = append(protoLayers, getProtoDesc(&layer))
|
||||||
|
}
|
||||||
|
|
||||||
|
return protoLayers
|
||||||
|
}
|
||||||
|
|
||||||
|
func getProtoDesc(descriptor *ispec.Descriptor) *proto_go.Descriptor {
|
||||||
|
if descriptor == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &proto_go.Descriptor{
|
||||||
|
MediaType: descriptor.MediaType,
|
||||||
|
Digest: descriptor.Digest.String(),
|
||||||
|
Size: descriptor.Size,
|
||||||
|
URLs: descriptor.URLs,
|
||||||
|
Annotations: descriptor.Annotations,
|
||||||
|
Data: descriptor.Data,
|
||||||
|
Platform: GetProtoPlatform(descriptor.Platform),
|
||||||
|
ArtifactType: &descriptor.ArtifactType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getProtoManifestList(manifests []ispec.Descriptor) []*proto_go.Descriptor {
|
||||||
|
result := make([]*proto_go.Descriptor, 0, len(manifests))
|
||||||
|
|
||||||
|
for _, manifest := range manifests {
|
||||||
|
result = append(result, &proto_go.Descriptor{
|
||||||
|
MediaType: manifest.MediaType,
|
||||||
|
Digest: manifest.Digest.String(),
|
||||||
|
Size: manifest.Size,
|
||||||
|
URLs: manifest.URLs,
|
||||||
|
Annotations: manifest.Annotations,
|
||||||
|
Data: manifest.Data,
|
||||||
|
Platform: GetProtoPlatform(manifest.Platform),
|
||||||
|
ArtifactType: ref(manifest.ArtifactType),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProtoPlatform(platform *ispec.Platform) *proto_go.Platform {
|
||||||
|
if platform == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &proto_go.Platform{
|
||||||
|
Architecture: platform.Architecture,
|
||||||
|
OS: platform.OS,
|
||||||
|
OSVersion: ref(platform.OSVersion),
|
||||||
|
OSFeatures: platform.OSFeatures,
|
||||||
|
Variant: ref(platform.Variant),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getProtoHistory(historySlice []ispec.History) []*proto_go.History {
|
||||||
|
protoHistory := []*proto_go.History{}
|
||||||
|
|
||||||
|
for _, history := range historySlice {
|
||||||
|
history := history
|
||||||
|
|
||||||
|
protoHistory = append(protoHistory, &proto_go.History{
|
||||||
|
Created: GetProtoTime(history.Created),
|
||||||
|
CreatedBy: &history.CreatedBy,
|
||||||
|
Author: &history.Author,
|
||||||
|
Comment: &history.Comment,
|
||||||
|
EmptyLayer: &history.EmptyLayer,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return protoHistory
|
||||||
|
}
|
||||||
|
|
||||||
|
func getProtoDiffIDs(digests []godigest.Digest) []string {
|
||||||
|
digestsStr := []string{}
|
||||||
|
|
||||||
|
for _, digest := range digests {
|
||||||
|
digestsStr = append(digestsStr, digest.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
return digestsStr
|
||||||
|
}
|
||||||
|
|
||||||
|
func getProtoExposedPorts(exposedPorts map[string]struct{}) map[string]*proto_go.EmptyMessage {
|
||||||
|
protoPorts := map[string]*proto_go.EmptyMessage{}
|
||||||
|
|
||||||
|
for i := range exposedPorts {
|
||||||
|
protoPorts[i] = &proto_go.EmptyMessage{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return protoPorts
|
||||||
|
}
|
||||||
|
|
||||||
|
func getProtoConfigVolumes(volumes map[string]struct{}) map[string]*proto_go.EmptyMessage {
|
||||||
|
protoVolumes := map[string]*proto_go.EmptyMessage{}
|
||||||
|
|
||||||
|
for i := range volumes {
|
||||||
|
protoVolumes[i] = &proto_go.EmptyMessage{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return protoVolumes
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProtoReferrerInfo(referrer mTypes.ReferrerInfo) *proto_go.ReferrerInfo {
|
||||||
|
return &proto_go.ReferrerInfo{
|
||||||
|
Digest: referrer.Digest,
|
||||||
|
MediaType: referrer.MediaType,
|
||||||
|
ArtifactType: referrer.ArtifactType,
|
||||||
|
Size: int64(referrer.Size),
|
||||||
|
Annotations: referrer.Annotations,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProtoTime(time *time.Time) *timestamppb.Timestamp {
|
||||||
|
if time == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return timestamppb.New(*time)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProtoTags(tags map[string]mTypes.Descriptor) map[string]*proto_go.TagDescriptor {
|
||||||
|
resultMap := map[string]*proto_go.TagDescriptor{}
|
||||||
|
|
||||||
|
for tag, tagDescriptor := range tags {
|
||||||
|
resultMap[tag] = &proto_go.TagDescriptor{
|
||||||
|
Digest: tagDescriptor.Digest,
|
||||||
|
MediaType: tagDescriptor.MediaType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProtoLastUpdatedImage(lastUpdatedImage *mTypes.LastUpdatedImage) *proto_go.RepoLastUpdatedImage {
|
||||||
|
if lastUpdatedImage == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &proto_go.RepoLastUpdatedImage{
|
||||||
|
LastUpdated: GetProtoTime(lastUpdatedImage.LastUpdated),
|
||||||
|
MediaType: lastUpdatedImage.MediaType,
|
||||||
|
Digest: lastUpdatedImage.Digest,
|
||||||
|
Tag: lastUpdatedImage.Tag,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProtoEarlierUpdatedImage(repoLastImage *proto_go.RepoLastUpdatedImage, lastImage *proto_go.RepoLastUpdatedImage,
|
||||||
|
) *proto_go.RepoLastUpdatedImage {
|
||||||
|
if repoLastImage == nil {
|
||||||
|
return lastImage
|
||||||
|
}
|
||||||
|
|
||||||
|
if lastImage == nil || lastImage.LastUpdated == nil {
|
||||||
|
return repoLastImage
|
||||||
|
}
|
||||||
|
|
||||||
|
if repoLastImage.LastUpdated == nil {
|
||||||
|
return lastImage
|
||||||
|
}
|
||||||
|
|
||||||
|
if repoLastImage.LastUpdated.AsTime().Before(lastImage.LastUpdated.AsTime()) {
|
||||||
|
return lastImage
|
||||||
|
}
|
||||||
|
|
||||||
|
return repoLastImage
|
||||||
|
}
|
||||||
|
|
||||||
|
func ref[T any](input T) *T {
|
||||||
|
ref := input
|
||||||
|
|
||||||
|
return &ref
|
||||||
|
}
|
||||||
|
|
||||||
|
func deref[T any](pointer *T, defaultVal T) T {
|
||||||
|
if pointer != nil {
|
||||||
|
return *pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultVal
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -29,8 +29,6 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repoMetaTablename := "RepoMetadataTable" + uuid.String()
|
repoMetaTablename := "RepoMetadataTable" + uuid.String()
|
||||||
manifestDataTablename := "ManifestDataTable" + uuid.String()
|
|
||||||
indexDataTablename := "IndexDataTable" + uuid.String()
|
|
||||||
userDataTablename := "UserDataTable" + uuid.String()
|
userDataTablename := "UserDataTable" + uuid.String()
|
||||||
apiKeyTablename := "ApiKeyTable" + uuid.String()
|
apiKeyTablename := "ApiKeyTable" + uuid.String()
|
||||||
|
|
||||||
@ -56,8 +54,6 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
dynamoWrapper := DynamoDB{
|
dynamoWrapper := DynamoDB{
|
||||||
Client: dynamodb.NewFromConfig(cfg),
|
Client: dynamodb.NewFromConfig(cfg),
|
||||||
RepoMetaTablename: repoMetaTablename,
|
RepoMetaTablename: repoMetaTablename,
|
||||||
ManifestDataTablename: manifestDataTablename,
|
|
||||||
IndexDataTablename: indexDataTablename,
|
|
||||||
VersionTablename: versionTablename,
|
VersionTablename: versionTablename,
|
||||||
UserDataTablename: userDataTablename,
|
UserDataTablename: userDataTablename,
|
||||||
APIKeyTablename: apiKeyTablename,
|
APIKeyTablename: apiKeyTablename,
|
||||||
@ -66,19 +62,13 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The table creation should fail as the endpoint is not configured correctly
|
// The table creation should fail as the endpoint is not configured correctly
|
||||||
err = dynamoWrapper.createRepoMetaTable()
|
err = dynamoWrapper.createTable(dynamoWrapper.RepoMetaTablename)
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.createManifestDataTable()
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.createIndexDataTable()
|
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
|
|
||||||
err = dynamoWrapper.createVersionTable()
|
err = dynamoWrapper.createVersionTable()
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
|
|
||||||
err = dynamoWrapper.createAPIKeyTable()
|
err = dynamoWrapper.createTable(dynamoWrapper.APIKeyTablename)
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -100,19 +90,14 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
dynamoWrapper := DynamoDB{
|
dynamoWrapper := DynamoDB{
|
||||||
Client: dynamodb.NewFromConfig(cfg),
|
Client: dynamodb.NewFromConfig(cfg),
|
||||||
RepoMetaTablename: repoMetaTablename,
|
RepoMetaTablename: repoMetaTablename,
|
||||||
ManifestDataTablename: manifestDataTablename,
|
|
||||||
VersionTablename: versionTablename,
|
VersionTablename: versionTablename,
|
||||||
IndexDataTablename: indexDataTablename,
|
|
||||||
UserDataTablename: userDataTablename,
|
UserDataTablename: userDataTablename,
|
||||||
Patches: version.GetDynamoDBPatches(),
|
Patches: version.GetDynamoDBPatches(),
|
||||||
Log: log.Logger{Logger: zerolog.New(os.Stdout)},
|
Log: log.Logger{Logger: zerolog.New(os.Stdout)},
|
||||||
}
|
}
|
||||||
|
|
||||||
// The tables were not created so delete calls fail, but dynamoWrapper should not error
|
// The tables were not created so delete calls fail, but dynamoWrapper should not error
|
||||||
err = dynamoWrapper.deleteRepoMetaTable()
|
err = dynamoWrapper.deleteTable(dynamoWrapper.RepoMetaTablename)
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.deleteManifestDataTable()
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package dynamodb_test
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go-v2/aws"
|
"github.com/aws/aws-sdk-go-v2/aws"
|
||||||
@ -12,8 +11,6 @@ import (
|
|||||||
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
|
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
|
||||||
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
|
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
|
||||||
guuid "github.com/gofrs/uuid"
|
guuid "github.com/gofrs/uuid"
|
||||||
"github.com/opencontainers/go-digest"
|
|
||||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
|
||||||
@ -40,9 +37,9 @@ func TestIterator(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repoMetaTablename := "RepoMetadataTable" + uuid.String()
|
repoMetaTablename := "RepoMetadataTable" + uuid.String()
|
||||||
manifestDataTablename := "ManifestDataTable" + uuid.String()
|
|
||||||
versionTablename := "Version" + uuid.String()
|
versionTablename := "Version" + uuid.String()
|
||||||
indexDataTablename := "IndexDataTable" + uuid.String()
|
imageMetaTablename := "ImageMeta" + uuid.String()
|
||||||
|
repoBlobsTablename := "RepoBlobs" + uuid.String()
|
||||||
userDataTablename := "UserDataTable" + uuid.String()
|
userDataTablename := "UserDataTable" + uuid.String()
|
||||||
apiKeyTablename := "ApiKeyTable" + uuid.String()
|
apiKeyTablename := "ApiKeyTable" + uuid.String()
|
||||||
|
|
||||||
@ -53,8 +50,8 @@ func TestIterator(t *testing.T) {
|
|||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
Region: region,
|
Region: region,
|
||||||
RepoMetaTablename: repoMetaTablename,
|
RepoMetaTablename: repoMetaTablename,
|
||||||
ManifestDataTablename: manifestDataTablename,
|
ImageMetaTablename: imageMetaTablename,
|
||||||
IndexDataTablename: indexDataTablename,
|
RepoBlobsInfoTablename: repoBlobsTablename,
|
||||||
VersionTablename: versionTablename,
|
VersionTablename: versionTablename,
|
||||||
APIKeyTablename: apiKeyTablename,
|
APIKeyTablename: apiKeyTablename,
|
||||||
UserDataTablename: userDataTablename,
|
UserDataTablename: userDataTablename,
|
||||||
@ -65,21 +62,21 @@ func TestIterator(t *testing.T) {
|
|||||||
dynamoWrapper, err := mdynamodb.New(client, params, log)
|
dynamoWrapper, err := mdynamodb.New(client, params, log)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
So(dynamoWrapper.ResetManifestDataTable(), ShouldBeNil)
|
So(dynamoWrapper.ResetTable(dynamoWrapper.ImageMetaTablename), ShouldBeNil)
|
||||||
So(dynamoWrapper.ResetRepoMetaTable(), ShouldBeNil)
|
So(dynamoWrapper.ResetTable(dynamoWrapper.RepoMetaTablename), ShouldBeNil)
|
||||||
|
|
||||||
err = dynamoWrapper.SetRepoReference("repo1", "tag1", "manifestType", "manifestDigest1")
|
err = dynamoWrapper.SetRepoReference("repo1", "tag1", CreateRandomImage().AsImageMeta())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
err = dynamoWrapper.SetRepoReference("repo2", "tag2", "manifestType", "manifestDigest2")
|
err = dynamoWrapper.SetRepoReference("repo2", "tag2", CreateRandomImage().AsImageMeta())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
err = dynamoWrapper.SetRepoReference("repo3", "tag3", "manifestType", "manifestDigest3")
|
err = dynamoWrapper.SetRepoReference("repo3", "tag3", CreateRandomImage().AsImageMeta())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
repoMetaAttributeIterator := mdynamodb.NewBaseDynamoAttributesIterator(
|
repoMetaAttributeIterator := mdynamodb.NewBaseDynamoAttributesIterator(
|
||||||
dynamoWrapper.Client,
|
dynamoWrapper.Client,
|
||||||
repoMetaTablename,
|
dynamoWrapper.RepoMetaTablename,
|
||||||
"RepoMetadata",
|
"RepoMetadata",
|
||||||
1,
|
1,
|
||||||
log,
|
log,
|
||||||
@ -143,12 +140,12 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repoMetaTablename := "RepoMetadataTable" + uuid.String()
|
repoMetaTablename := "RepoMetadataTable" + uuid.String()
|
||||||
manifestDataTablename := "ManifestDataTable" + uuid.String()
|
|
||||||
versionTablename := "Version" + uuid.String()
|
versionTablename := "Version" + uuid.String()
|
||||||
indexDataTablename := "IndexDataTable" + uuid.String()
|
|
||||||
userDataTablename := "UserDataTable" + uuid.String()
|
userDataTablename := "UserDataTable" + uuid.String()
|
||||||
apiKeyTablename := "ApiKeyTable" + uuid.String()
|
apiKeyTablename := "ApiKeyTable" + uuid.String()
|
||||||
wrongTableName := "WRONG Tables"
|
wrongTableName := "WRONG Tables"
|
||||||
|
imageMetaTablename := "ImageMeta" + uuid.String()
|
||||||
|
repoBlobsTablename := "RepoBlobs" + uuid.String()
|
||||||
|
|
||||||
log := log.NewLogger("debug", "")
|
log := log.NewLogger("debug", "")
|
||||||
|
|
||||||
@ -157,8 +154,8 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
Region: region,
|
Region: region,
|
||||||
RepoMetaTablename: repoMetaTablename,
|
RepoMetaTablename: repoMetaTablename,
|
||||||
ManifestDataTablename: manifestDataTablename,
|
ImageMetaTablename: imageMetaTablename,
|
||||||
IndexDataTablename: indexDataTablename,
|
RepoBlobsInfoTablename: repoBlobsTablename,
|
||||||
UserDataTablename: userDataTablename,
|
UserDataTablename: userDataTablename,
|
||||||
APIKeyTablename: apiKeyTablename,
|
APIKeyTablename: apiKeyTablename,
|
||||||
VersionTablename: versionTablename,
|
VersionTablename: versionTablename,
|
||||||
@ -174,8 +171,9 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
|
|
||||||
dynamoWrapper.SetImageTrustStore(imgTrustStore)
|
dynamoWrapper.SetImageTrustStore(imgTrustStore)
|
||||||
|
|
||||||
So(dynamoWrapper.ResetManifestDataTable(), ShouldBeNil) //nolint:contextcheck
|
So(dynamoWrapper.ResetTable(dynamoWrapper.RepoMetaTablename), ShouldBeNil) //nolint:contextcheck
|
||||||
So(dynamoWrapper.ResetRepoMetaTable(), ShouldBeNil) //nolint:contextcheck
|
So(dynamoWrapper.ResetTable(dynamoWrapper.ImageMetaTablename), ShouldBeNil) //nolint:contextcheck
|
||||||
|
So(dynamoWrapper.ResetTable(dynamoWrapper.UserDataTablename), ShouldBeNil) //nolint:contextcheck
|
||||||
|
|
||||||
userAc := reqCtx.NewUserAccessControl()
|
userAc := reqCtx.NewUserAccessControl()
|
||||||
userAc.SetUsername("test")
|
userAc.SetUsername("test")
|
||||||
@ -240,7 +238,7 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
|
|
||||||
status, err := dynamoWrapper.ToggleBookmarkRepo(ctx, "repo")
|
status, err := dynamoWrapper.ToggleBookmarkRepo(ctx, "repo")
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(status, ShouldEqual, mTypes.NotChanged)
|
So(status, ShouldEqual, mTypes.Added)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("ToggleBookmarkRepo GetUserMeta client error", func() {
|
Convey("ToggleBookmarkRepo GetUserMeta client error", func() {
|
||||||
@ -476,608 +474,6 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("SetManifestData", func() {
|
|
||||||
dynamoWrapper.ManifestDataTablename = wrongTableName
|
|
||||||
|
|
||||||
err := dynamoWrapper.SetManifestData("dig", mTypes.ManifestData{})
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetManifestData", func() {
|
|
||||||
dynamoWrapper.ManifestDataTablename = wrongTableName
|
|
||||||
|
|
||||||
_, err := dynamoWrapper.GetManifestData("dig")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetManifestData unmarshal error", func() {
|
|
||||||
err := setBadManifestData(dynamoWrapper.Client, manifestDataTablename, "dig")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, err = dynamoWrapper.GetManifestData("dig")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetIndexData", func() {
|
|
||||||
dynamoWrapper.IndexDataTablename = wrongTableName
|
|
||||||
|
|
||||||
_, err := dynamoWrapper.GetIndexData("dig")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetIndexData unmarshal error", func() {
|
|
||||||
err := setBadIndexData(dynamoWrapper.Client, indexDataTablename, "dig")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, err = dynamoWrapper.GetManifestData("dig")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SetManifestMeta GetRepoMeta error", func() {
|
|
||||||
err := setBadRepoMeta(dynamoWrapper.Client, repoMetaTablename, "repo1")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.SetManifestMeta("repo1", "dig", mTypes.ManifestMetadata{})
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetManifestMeta GetManifestData not found error", func() {
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", "tag", "dig", "")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, err = dynamoWrapper.GetManifestMeta("repo", "dig")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetManifestMeta GetRepoMeta Not Found error", func() {
|
|
||||||
err := dynamoWrapper.SetManifestData("dig", mTypes.ManifestData{})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, err = dynamoWrapper.GetManifestMeta("repoNotFound", "dig")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetManifestMeta GetRepoMeta error", func() {
|
|
||||||
err := dynamoWrapper.SetManifestData("dig", mTypes.ManifestData{})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = setBadRepoMeta(dynamoWrapper.Client, repoMetaTablename, "repo")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, err = dynamoWrapper.GetManifestMeta("repo", "dig")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SetRepoReference client error", func() {
|
|
||||||
dynamoWrapper.RepoMetaTablename = badTablename
|
|
||||||
digest := digest.FromString("str")
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", digest.String(), digest, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SetReferrer client error", func() {
|
|
||||||
dynamoWrapper.RepoMetaTablename = badTablename
|
|
||||||
err := dynamoWrapper.SetReferrer("repo", "", mTypes.ReferrerInfo{})
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SetReferrer bad repoMeta", func() {
|
|
||||||
err := setBadRepoMeta(dynamoWrapper.Client, repoMetaTablename, "repo")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.SetReferrer("repo", "", mTypes.ReferrerInfo{})
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetReferrers client error", func() {
|
|
||||||
dynamoWrapper.RepoMetaTablename = badTablename
|
|
||||||
_, err := dynamoWrapper.GetReferrers("repo", "")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetReferrers bad repoMeta", func() {
|
|
||||||
err := setBadRepoMeta(dynamoWrapper.Client, repoMetaTablename, "repo")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, err = dynamoWrapper.GetReferrers("repo", "")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("DeleteReferrer client error", func() {
|
|
||||||
dynamoWrapper.RepoMetaTablename = badTablename
|
|
||||||
err := dynamoWrapper.DeleteReferrer("repo", "", "")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("DeleteReferrer bad repoMeta", func() {
|
|
||||||
err := setBadRepoMeta(dynamoWrapper.Client, repoMetaTablename, "repo")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.DeleteReferrer("repo", "", "")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetReferrersInfo GetReferrers errors", func() {
|
|
||||||
dynamoWrapper.RepoMetaTablename = badTablename
|
|
||||||
_, err := dynamoWrapper.GetReferrersInfo("repo", "", nil)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetReferrersInfo getData fails", func() {
|
|
||||||
dynamoWrapper.ManifestDataTablename = badTablename
|
|
||||||
err = dynamoWrapper.SetReferrer("repo", "rf", mTypes.ReferrerInfo{
|
|
||||||
Digest: "dig1",
|
|
||||||
MediaType: ispec.MediaTypeImageManifest,
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.SetReferrer("repo", "rf", mTypes.ReferrerInfo{
|
|
||||||
Digest: "dig2",
|
|
||||||
MediaType: ispec.MediaTypeImageManifest,
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, err := dynamoWrapper.GetReferrersInfo("repo", "rf", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetReferrersInfo bad descriptor blob", func() {
|
|
||||||
err = dynamoWrapper.SetManifestData("dig3", mTypes.ManifestData{
|
|
||||||
ManifestBlob: []byte("bad json"),
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.SetReferrer("repo", "rf", mTypes.ReferrerInfo{
|
|
||||||
Digest: "dig2",
|
|
||||||
MediaType: ispec.MediaTypeImageManifest,
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.SetReferrer("repo", "rf", mTypes.ReferrerInfo{
|
|
||||||
Digest: "dig3",
|
|
||||||
MediaType: ispec.MediaTypeImageManifest,
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, err := dynamoWrapper.GetReferrersInfo("repo", "rf", nil)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("IncrementRepoStars GetRepoMeta error", func() {
|
|
||||||
err = dynamoWrapper.IncrementRepoStars("repo")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("DecrementRepoStars GetRepoMeta error", func() {
|
|
||||||
err = dynamoWrapper.DecrementRepoStars("repo")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("DeleteRepoTag Client.GetItem error", func() {
|
|
||||||
strSlice := make([]string, 10000)
|
|
||||||
repoName := strings.Join(strSlice, ".")
|
|
||||||
|
|
||||||
err = dynamoWrapper.DeleteRepoTag(repoName, "tag")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("DeleteRepoTag unmarshal error", func() {
|
|
||||||
err = setBadRepoMeta(dynamoWrapper.Client, repoMetaTablename, "repo")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.DeleteRepoTag("repo", "tag")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetRepoMeta Client.GetItem error", func() {
|
|
||||||
strSlice := make([]string, 10000)
|
|
||||||
repoName := strings.Join(strSlice, ".")
|
|
||||||
|
|
||||||
_, err = dynamoWrapper.GetRepoMeta(repoName)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetRepoMeta unmarshal error", func() {
|
|
||||||
err = setBadRepoMeta(dynamoWrapper.Client, repoMetaTablename, "repo")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, err = dynamoWrapper.GetRepoMeta("repo")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("IncrementImageDownloads GetRepoMeta error", func() {
|
|
||||||
err = dynamoWrapper.IncrementImageDownloads("repoNotFound", "")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("IncrementImageDownloads tag not found error", func() {
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", "tag", "dig", "")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.IncrementImageDownloads("repo", "notFoundTag")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("UpdateSignaturesValidity GetManifestData error", func() {
|
|
||||||
err := setBadManifestData(dynamoWrapper.Client, manifestDataTablename, "dig")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.UpdateSignaturesValidity("repo", "dig")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.UpdateSignaturesValidity("repo", digest.FromString("dig"))
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("UpdateSignaturesValidity GetRepoMeta error", func() {
|
|
||||||
err := dynamoWrapper.SetManifestData("dig", mTypes.ManifestData{})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = setBadRepoMeta(dynamoWrapper.Client, repoMetaTablename, "repo")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.UpdateSignaturesValidity("repo", "dig")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("AddManifestSignature GetRepoMeta error", func() {
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", "tag", "dig", "")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.AddManifestSignature("repoNotFound", "tag", mTypes.SignatureMetadata{})
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("AddManifestSignature ManifestSignatures signedManifestDigest not found error", func() {
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", "tag", "dig", "")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.AddManifestSignature("repo", "tagNotFound", mTypes.SignatureMetadata{})
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("AddManifestSignature SignatureType metadb.NotationType", func() {
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", "tag", "dig", "")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.AddManifestSignature("repo", "tagNotFound", mTypes.SignatureMetadata{
|
|
||||||
SignatureType: "notation",
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("DeleteSignature GetRepoMeta error", func() {
|
|
||||||
err = dynamoWrapper.DeleteSignature("repoNotFound", "tagNotFound", mTypes.SignatureMetadata{})
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("DeleteSignature sigDigest.SignatureManifestDigest != sigMeta.SignatureDigest true", func() {
|
|
||||||
err := setRepoMeta(dynamoWrapper.Client, repoMetaTablename, mTypes.RepoMetadata{
|
|
||||||
Name: "repo",
|
|
||||||
Signatures: map[string]mTypes.ManifestSignatures{
|
|
||||||
"tag1": {
|
|
||||||
"cosign": []mTypes.SignatureInfo{
|
|
||||||
{SignatureManifestDigest: "dig1"},
|
|
||||||
{SignatureManifestDigest: "dig2"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.DeleteSignature("repo", "tag1", mTypes.SignatureMetadata{
|
|
||||||
SignatureDigest: "dig2",
|
|
||||||
SignatureType: "cosign",
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetMultipleRepoMeta unmarshal error", func() {
|
|
||||||
err = setBadRepoMeta(dynamoWrapper.Client, repoMetaTablename, "repo") //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, err = dynamoWrapper.GetMultipleRepoMeta(ctx, func(repoMeta mTypes.RepoMetadata) bool { return true })
|
|
||||||
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SearchRepos repoMeta unmarshal error", func() {
|
|
||||||
err = setBadRepoMeta(dynamoWrapper.Client, repoMetaTablename, "repo") //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.SearchRepos(ctx, "")
|
|
||||||
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SearchRepos bad tablename", func() {
|
|
||||||
dynamoWrapper.RepoMetaTablename = badTablename
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.SearchRepos(ctx, "")
|
|
||||||
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetMultipleRepoMeta bad tablename", func() {
|
|
||||||
dynamoWrapper.RepoMetaTablename = badTablename
|
|
||||||
|
|
||||||
_, err = dynamoWrapper.GetMultipleRepoMeta(ctx, func(repoMeta mTypes.RepoMetadata) bool { return true })
|
|
||||||
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("FilterTags bad tablename", func() {
|
|
||||||
dynamoWrapper.RepoMetaTablename = badTablename
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.FilterTags(ctx,
|
|
||||||
func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool {
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("FilterRepos bad tablename", func() {
|
|
||||||
dynamoWrapper.RepoMetaTablename = badTablename
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.FilterRepos(ctx, func(repoMeta mTypes.RepoMetadata) bool { return true })
|
|
||||||
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SearchTags bad tablename", func() {
|
|
||||||
dynamoWrapper.RepoMetaTablename = badTablename
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.SearchTags(ctx, "repo:tag")
|
|
||||||
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SearchRepos GetManifestMeta error", func() {
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", "tag1", "notFoundDigest", //nolint:contextcheck
|
|
||||||
ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.SearchRepos(ctx, "")
|
|
||||||
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Unsuported type", func() {
|
|
||||||
digest := digest.FromString("digest")
|
|
||||||
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", "tag1", digest, "invalid type") //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.SearchRepos(ctx, "")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.SearchTags(ctx, "repo:")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.FilterTags(ctx,
|
|
||||||
func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool { return true })
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SearchRepos bad index data", func() {
|
|
||||||
indexDigest := digest.FromString("indexDigest")
|
|
||||||
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", "tag1", indexDigest, ispec.MediaTypeImageIndex) //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = setBadIndexData(dynamoWrapper.Client, indexDataTablename, indexDigest.String()) //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.SearchRepos(ctx, "")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SearchRepos bad indexBlob in IndexData", func() {
|
|
||||||
indexDigest := digest.FromString("indexDigest")
|
|
||||||
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", "tag1", indexDigest, ispec.MediaTypeImageIndex) //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.SetIndexData(indexDigest, mTypes.IndexData{ //nolint:contextcheck
|
|
||||||
IndexBlob: []byte("bad json"),
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.SearchRepos(ctx, "")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SearchTags repoMeta unmarshal error", func() {
|
|
||||||
err = setBadRepoMeta(dynamoWrapper.Client, repoMetaTablename, "repo") //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.SearchTags(ctx, "repo:")
|
|
||||||
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SearchTags GetManifestMeta error", func() {
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", "tag1", "manifestNotFound", //nolint:contextcheck
|
|
||||||
ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.SearchTags(ctx, "repo:")
|
|
||||||
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SearchTags bad index data", func() {
|
|
||||||
indexDigest := digest.FromString("indexDigest")
|
|
||||||
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", "tag1", indexDigest, ispec.MediaTypeImageIndex) //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = setBadIndexData(dynamoWrapper.Client, indexDataTablename, indexDigest.String()) //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.SearchTags(ctx, "repo:")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SearchTags bad indexBlob in IndexData", func() {
|
|
||||||
indexDigest := digest.FromString("indexDigest")
|
|
||||||
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", "tag1", indexDigest, ispec.MediaTypeImageIndex) //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.SetIndexData(indexDigest, mTypes.IndexData{ //nolint:contextcheck
|
|
||||||
IndexBlob: []byte("bad json"),
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.SearchTags(ctx, "repo:")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SearchRepos attr", func() {
|
|
||||||
err = setBadRepoMeta(dynamoWrapper.Client, repoMetaTablename, "repo") //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err := dynamoWrapper.SearchRepos(ctx, "repo")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("FilterRepos attributevalue.Unmarshal(repoMetaAttribute) errors", func() {
|
|
||||||
dynamoWrapper.RepoMetaTablename = "bad-table-FilterRepos"
|
|
||||||
|
|
||||||
_, _, _, err := dynamoWrapper.FilterRepos(ctx, func(repoMeta mTypes.RepoMetadata) bool {
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SearchRepos bad RepoMeta table name", func() {
|
|
||||||
dynamoWrapper.RepoMetaTablename = "SearchRepos-bad-table"
|
|
||||||
|
|
||||||
_, _, _, err := dynamoWrapper.SearchRepos(ctx, "repo")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("FilterTags repoMeta unmarshal error", func() {
|
|
||||||
err = setBadRepoMeta(dynamoWrapper.Client, repoMetaTablename, "repo") //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.FilterTags(ctx,
|
|
||||||
func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool {
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("FilterTags bad RepoMeta table name", func() {
|
|
||||||
dynamoWrapper.RepoMetaTablename = "bad-table"
|
|
||||||
|
|
||||||
_, _, _, err := dynamoWrapper.FilterTags(ctx,
|
|
||||||
func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool {
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("FilterTags manifestMeta not found", func() {
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", "tag1", "manifestNotFound", //nolint:contextcheck
|
|
||||||
ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.FilterTags(ctx,
|
|
||||||
func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool {
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("FilterTags manifestMeta unmarshal error", func() {
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", "tag1", "dig", ispec.MediaTypeImageManifest) //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = setBadManifestData(dynamoWrapper.Client, manifestDataTablename, "dig") //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.FilterTags(
|
|
||||||
ctx,
|
|
||||||
func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool {
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("FilterTags bad IndexData", func() {
|
|
||||||
indexDigest := digest.FromString("indexDigest")
|
|
||||||
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", "tag1", indexDigest, ispec.MediaTypeImageIndex) //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = setBadIndexData(dynamoWrapper.Client, indexDataTablename, indexDigest.String()) //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.FilterTags(ctx,
|
|
||||||
func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool { return true })
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("FilterTags bad indexBlob in IndexData", func() {
|
|
||||||
indexDigest := digest.FromString("indexDigest")
|
|
||||||
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", "tag1", indexDigest, ispec.MediaTypeImageIndex) //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.SetIndexData(indexDigest, mTypes.IndexData{ //nolint:contextcheck
|
|
||||||
IndexBlob: []byte("bad json"),
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.FilterTags(ctx,
|
|
||||||
func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool { return true })
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("FilterTags didn't match any index manifest", func() {
|
|
||||||
var (
|
|
||||||
indexDigest = digest.FromString("indexDigest")
|
|
||||||
manifestDigestFromIndex1 = digest.FromString("manifestDigestFromIndex1")
|
|
||||||
manifestDigestFromIndex2 = digest.FromString("manifestDigestFromIndex2")
|
|
||||||
)
|
|
||||||
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", "tag1", indexDigest, ispec.MediaTypeImageIndex) //nolint:contextcheck
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
indexBlob, err := GetIndexBlobWithManifests([]digest.Digest{
|
|
||||||
manifestDigestFromIndex1, manifestDigestFromIndex2,
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.SetIndexData(indexDigest, mTypes.IndexData{ //nolint:contextcheck
|
|
||||||
IndexBlob: indexBlob,
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.SetManifestData(manifestDigestFromIndex1, mTypes.ManifestData{ //nolint:contextcheck
|
|
||||||
ManifestBlob: []byte("{}"),
|
|
||||||
ConfigBlob: []byte("{}"),
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = dynamoWrapper.SetManifestData(manifestDigestFromIndex2, mTypes.ManifestData{ //nolint:contextcheck
|
|
||||||
ManifestBlob: []byte("{}"),
|
|
||||||
ConfigBlob: []byte("{}"),
|
|
||||||
})
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = dynamoWrapper.FilterTags(ctx,
|
|
||||||
func(repoMeta mTypes.RepoMetadata, manifestMeta mTypes.ManifestMetadata) bool { return false })
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("PatchDB dwr.getDBVersion errors", func() {
|
Convey("PatchDB dwr.getDBVersion errors", func() {
|
||||||
dynamoWrapper.VersionTablename = badTablename
|
dynamoWrapper.VersionTablename = badTablename
|
||||||
|
|
||||||
@ -1102,7 +498,7 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
Convey("ResetRepoMetaTable client errors", func() {
|
Convey("ResetRepoMetaTable client errors", func() {
|
||||||
dynamoWrapper.RepoMetaTablename = badTablename
|
dynamoWrapper.RepoMetaTablename = badTablename
|
||||||
|
|
||||||
err := dynamoWrapper.ResetRepoMetaTable()
|
err := dynamoWrapper.ResetTable(dynamoWrapper.RepoMetaTablename)
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1112,49 +508,6 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
err := dynamoWrapper.PatchDB()
|
err := dynamoWrapper.PatchDB()
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("GetUserRepoMeta client.GetItem error", func() {
|
|
||||||
dynamoWrapper.RepoMetaTablename = badTablename
|
|
||||||
|
|
||||||
_, err = dynamoWrapper.GetUserRepoMeta(ctx, "repo")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetUserRepoMeta repoMeta not found", func() {
|
|
||||||
_, err = dynamoWrapper.GetUserRepoMeta(ctx, "unknown-repo-meta")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetUserRepoMeta userMeta not found", func() {
|
|
||||||
err := dynamoWrapper.SetRepoReference("repo", "tag", digest.FromString("1"), ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
dynamoWrapper.UserDataTablename = badTablename
|
|
||||||
|
|
||||||
userAc := reqCtx.NewUserAccessControl()
|
|
||||||
userAc.SetUsername("username")
|
|
||||||
userAc.SetGlobPatterns("read", map[string]bool{
|
|
||||||
"repo": true,
|
|
||||||
})
|
|
||||||
ctx := userAc.DeriveContext(context.Background())
|
|
||||||
|
|
||||||
_, err = dynamoWrapper.GetUserRepoMeta(ctx, "repo")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetUserRepoMeta unmarshal error", func() {
|
|
||||||
err := setBadRepoMeta(dynamoWrapper.Client, repoMetaTablename, "repo")
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
userAc := reqCtx.NewUserAccessControl()
|
|
||||||
userAc.SetUsername("username")
|
|
||||||
userAc.SetGlobPatterns("read", map[string]bool{
|
|
||||||
"repo": true,
|
|
||||||
})
|
|
||||||
ctx := userAc.DeriveContext(context.Background())
|
|
||||||
|
|
||||||
_, err = dynamoWrapper.GetUserRepoMeta(ctx, "repo")
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("NewDynamoDBWrapper errors", t, func() {
|
Convey("NewDynamoDBWrapper errors", t, func() {
|
||||||
@ -1162,8 +515,8 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
Region: region,
|
Region: region,
|
||||||
RepoMetaTablename: "",
|
RepoMetaTablename: "",
|
||||||
ManifestDataTablename: manifestDataTablename,
|
ImageMetaTablename: imageMetaTablename,
|
||||||
IndexDataTablename: indexDataTablename,
|
RepoBlobsInfoTablename: repoBlobsTablename,
|
||||||
UserDataTablename: userDataTablename,
|
UserDataTablename: userDataTablename,
|
||||||
APIKeyTablename: apiKeyTablename,
|
APIKeyTablename: apiKeyTablename,
|
||||||
VersionTablename: versionTablename,
|
VersionTablename: versionTablename,
|
||||||
@ -1178,40 +531,8 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
Region: region,
|
Region: region,
|
||||||
RepoMetaTablename: repoMetaTablename,
|
RepoMetaTablename: repoMetaTablename,
|
||||||
ManifestDataTablename: "",
|
ImageMetaTablename: imageMetaTablename,
|
||||||
IndexDataTablename: indexDataTablename,
|
RepoBlobsInfoTablename: repoBlobsTablename,
|
||||||
UserDataTablename: userDataTablename,
|
|
||||||
APIKeyTablename: apiKeyTablename,
|
|
||||||
VersionTablename: versionTablename,
|
|
||||||
}
|
|
||||||
client, err = mdynamodb.GetDynamoClient(params)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, err = mdynamodb.New(client, params, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
params = mdynamodb.DBDriverParameters{ //nolint:contextcheck
|
|
||||||
Endpoint: endpoint,
|
|
||||||
Region: region,
|
|
||||||
RepoMetaTablename: repoMetaTablename,
|
|
||||||
ManifestDataTablename: manifestDataTablename,
|
|
||||||
IndexDataTablename: "",
|
|
||||||
UserDataTablename: userDataTablename,
|
|
||||||
APIKeyTablename: apiKeyTablename,
|
|
||||||
VersionTablename: versionTablename,
|
|
||||||
}
|
|
||||||
client, err = mdynamodb.GetDynamoClient(params)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, err = mdynamodb.New(client, params, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
params = mdynamodb.DBDriverParameters{ //nolint:contextcheck
|
|
||||||
Endpoint: endpoint,
|
|
||||||
Region: region,
|
|
||||||
RepoMetaTablename: repoMetaTablename,
|
|
||||||
ManifestDataTablename: manifestDataTablename,
|
|
||||||
IndexDataTablename: indexDataTablename,
|
|
||||||
UserDataTablename: userDataTablename,
|
UserDataTablename: userDataTablename,
|
||||||
APIKeyTablename: apiKeyTablename,
|
APIKeyTablename: apiKeyTablename,
|
||||||
VersionTablename: "",
|
VersionTablename: "",
|
||||||
@ -1226,24 +547,8 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
Region: region,
|
Region: region,
|
||||||
RepoMetaTablename: repoMetaTablename,
|
RepoMetaTablename: repoMetaTablename,
|
||||||
ManifestDataTablename: manifestDataTablename,
|
ImageMetaTablename: imageMetaTablename,
|
||||||
IndexDataTablename: indexDataTablename,
|
RepoBlobsInfoTablename: repoBlobsTablename,
|
||||||
VersionTablename: versionTablename,
|
|
||||||
UserDataTablename: userDataTablename,
|
|
||||||
APIKeyTablename: apiKeyTablename,
|
|
||||||
}
|
|
||||||
client, err = mdynamodb.GetDynamoClient(params)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
_, err = mdynamodb.New(client, params, log)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
params = mdynamodb.DBDriverParameters{ //nolint:contextcheck
|
|
||||||
Endpoint: endpoint,
|
|
||||||
Region: region,
|
|
||||||
RepoMetaTablename: repoMetaTablename,
|
|
||||||
ManifestDataTablename: manifestDataTablename,
|
|
||||||
IndexDataTablename: indexDataTablename,
|
|
||||||
VersionTablename: versionTablename,
|
VersionTablename: versionTablename,
|
||||||
UserDataTablename: "",
|
UserDataTablename: "",
|
||||||
APIKeyTablename: apiKeyTablename,
|
APIKeyTablename: apiKeyTablename,
|
||||||
@ -1258,8 +563,8 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
Region: region,
|
Region: region,
|
||||||
RepoMetaTablename: repoMetaTablename,
|
RepoMetaTablename: repoMetaTablename,
|
||||||
ManifestDataTablename: manifestDataTablename,
|
ImageMetaTablename: imageMetaTablename,
|
||||||
IndexDataTablename: indexDataTablename,
|
RepoBlobsInfoTablename: repoBlobsTablename,
|
||||||
VersionTablename: versionTablename,
|
VersionTablename: versionTablename,
|
||||||
UserDataTablename: userDataTablename,
|
UserDataTablename: userDataTablename,
|
||||||
APIKeyTablename: "",
|
APIKeyTablename: "",
|
||||||
@ -1272,81 +577,6 @@ func TestWrapperErrors(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func setBadManifestData(client *dynamodb.Client, manifestDataTableName, digest string) error {
|
|
||||||
mdAttributeValue, err := attributevalue.Marshal("string")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = client.UpdateItem(context.TODO(), &dynamodb.UpdateItemInput{
|
|
||||||
ExpressionAttributeNames: map[string]string{
|
|
||||||
"#MD": "ManifestData",
|
|
||||||
},
|
|
||||||
ExpressionAttributeValues: map[string]types.AttributeValue{
|
|
||||||
":ManifestData": mdAttributeValue,
|
|
||||||
},
|
|
||||||
Key: map[string]types.AttributeValue{
|
|
||||||
"Digest": &types.AttributeValueMemberS{
|
|
||||||
Value: digest,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
TableName: aws.String(manifestDataTableName),
|
|
||||||
UpdateExpression: aws.String("SET #MD = :ManifestData"),
|
|
||||||
})
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func setBadRepoMeta(client *dynamodb.Client, repoMetadataTableName, repoName string) error {
|
|
||||||
repoAttributeValue, err := attributevalue.Marshal("string")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = client.UpdateItem(context.TODO(), &dynamodb.UpdateItemInput{
|
|
||||||
ExpressionAttributeNames: map[string]string{
|
|
||||||
"#RM": "RepoMetadata",
|
|
||||||
},
|
|
||||||
ExpressionAttributeValues: map[string]types.AttributeValue{
|
|
||||||
":RepoMetadata": repoAttributeValue,
|
|
||||||
},
|
|
||||||
Key: map[string]types.AttributeValue{
|
|
||||||
"RepoName": &types.AttributeValueMemberS{
|
|
||||||
Value: repoName,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
TableName: aws.String(repoMetadataTableName),
|
|
||||||
UpdateExpression: aws.String("SET #RM = :RepoMetadata"),
|
|
||||||
})
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func setBadIndexData(client *dynamodb.Client, indexDataTableName, digest string) error {
|
|
||||||
mdAttributeValue, err := attributevalue.Marshal("string")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = client.UpdateItem(context.TODO(), &dynamodb.UpdateItemInput{
|
|
||||||
ExpressionAttributeNames: map[string]string{
|
|
||||||
"#ID": "IndexData",
|
|
||||||
},
|
|
||||||
ExpressionAttributeValues: map[string]types.AttributeValue{
|
|
||||||
":IndexData": mdAttributeValue,
|
|
||||||
},
|
|
||||||
Key: map[string]types.AttributeValue{
|
|
||||||
"IndexDigest": &types.AttributeValueMemberS{
|
|
||||||
Value: digest,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
TableName: aws.String(indexDataTableName),
|
|
||||||
UpdateExpression: aws.String("SET #ID = :IndexData"),
|
|
||||||
})
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func setBadUserData(client *dynamodb.Client, userDataTablename, userID string) error {
|
func setBadUserData(client *dynamodb.Client, userDataTablename, userID string) error {
|
||||||
userAttributeValue, err := attributevalue.Marshal("string")
|
userAttributeValue, err := attributevalue.Marshal("string")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1361,7 +591,7 @@ func setBadUserData(client *dynamodb.Client, userDataTablename, userID string) e
|
|||||||
":UserData": userAttributeValue,
|
":UserData": userAttributeValue,
|
||||||
},
|
},
|
||||||
Key: map[string]types.AttributeValue{
|
Key: map[string]types.AttributeValue{
|
||||||
"Identity": &types.AttributeValueMemberS{
|
"Key": &types.AttributeValueMemberS{
|
||||||
Value: userID,
|
Value: userID,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1386,7 +616,7 @@ func setVersion(client *dynamodb.Client, versionTablename string, version string
|
|||||||
":Version": mdAttributeValue,
|
":Version": mdAttributeValue,
|
||||||
},
|
},
|
||||||
Key: map[string]types.AttributeValue{
|
Key: map[string]types.AttributeValue{
|
||||||
"VersionKey": &types.AttributeValueMemberS{
|
"Key": &types.AttributeValueMemberS{
|
||||||
Value: "DBVersion",
|
Value: "DBVersion",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1396,28 +626,3 @@ func setVersion(client *dynamodb.Client, versionTablename string, version string
|
|||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func setRepoMeta(client *dynamodb.Client, repoMetadataTableName string, repoMeta mTypes.RepoMetadata) error {
|
|
||||||
repoAttributeValue, err := attributevalue.Marshal(repoMeta)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = client.UpdateItem(context.TODO(), &dynamodb.UpdateItemInput{
|
|
||||||
ExpressionAttributeNames: map[string]string{
|
|
||||||
"#RM": "RepoMetadata",
|
|
||||||
},
|
|
||||||
ExpressionAttributeValues: map[string]types.AttributeValue{
|
|
||||||
":RepoMetadata": repoAttributeValue,
|
|
||||||
},
|
|
||||||
Key: map[string]types.AttributeValue{
|
|
||||||
"RepoName": &types.AttributeValueMemberS{
|
|
||||||
Value: repoMeta.Name,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
TableName: aws.String(repoMetadataTableName),
|
|
||||||
UpdateExpression: aws.String("SET #RM = :RepoMetadata"),
|
|
||||||
})
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type DBDriverParameters struct {
|
type DBDriverParameters struct {
|
||||||
Endpoint, Region, RepoMetaTablename, ManifestDataTablename, IndexDataTablename,
|
Endpoint, Region, RepoMetaTablename, RepoBlobsInfoTablename, ImageMetaTablename,
|
||||||
UserDataTablename, APIKeyTablename, VersionTablename string
|
UserDataTablename, APIKeyTablename, VersionTablename string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,10 +2,10 @@ package meta
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
godigest "github.com/opencontainers/go-digest"
|
godigest "github.com/opencontainers/go-digest"
|
||||||
|
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
|
||||||
zcommon "zotregistry.io/zot/pkg/common"
|
zcommon "zotregistry.io/zot/pkg/common"
|
||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
"zotregistry.io/zot/pkg/meta/common"
|
|
||||||
mTypes "zotregistry.io/zot/pkg/meta/types"
|
mTypes "zotregistry.io/zot/pkg/meta/types"
|
||||||
"zotregistry.io/zot/pkg/storage"
|
"zotregistry.io/zot/pkg/storage"
|
||||||
)
|
)
|
||||||
@ -22,55 +22,9 @@ func OnUpdateManifest(repo, reference, mediaType string, digest godigest.Digest,
|
|||||||
|
|
||||||
imgStore := storeController.GetImageStore(repo)
|
imgStore := storeController.GetImageStore(repo)
|
||||||
|
|
||||||
// check if image is a signature
|
err := SetImageMetaFromInput(repo, reference, mediaType, digest, body,
|
||||||
isSignature, signatureType, signedManifestDigest, err := storage.CheckIsImageSignature(repo, body, reference)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Msg("can't check if image is a signature or not")
|
|
||||||
|
|
||||||
if err := imgStore.DeleteImageManifest(repo, reference, false); err != nil {
|
|
||||||
log.Error().Err(err).Str("manifest", reference).Str("repository", repo).Msg("couldn't remove image manifest in repo")
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
metadataSuccessfullySet := true
|
|
||||||
|
|
||||||
if isSignature {
|
|
||||||
layersInfo, errGetLayers := GetSignatureLayersInfo(repo, reference, digest.String(), signatureType, body,
|
|
||||||
imgStore, log)
|
|
||||||
if errGetLayers != nil {
|
|
||||||
metadataSuccessfullySet = false
|
|
||||||
err = errGetLayers
|
|
||||||
} else {
|
|
||||||
err = metaDB.AddManifestSignature(repo, signedManifestDigest, mTypes.SignatureMetadata{
|
|
||||||
SignatureType: signatureType,
|
|
||||||
SignatureDigest: digest.String(),
|
|
||||||
LayersInfo: layersInfo,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Msg("metadb: error while putting repo meta")
|
|
||||||
metadataSuccessfullySet = false
|
|
||||||
} else {
|
|
||||||
err = metaDB.UpdateSignaturesValidity(repo, signedManifestDigest)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Str("repository", repo).Str("reference", reference).Str("digest",
|
|
||||||
signedManifestDigest.String()).Msg("metadb: failed verify signatures validity for signed image")
|
|
||||||
metadataSuccessfullySet = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err = SetImageMetaFromInput(repo, reference, mediaType, digest, body,
|
|
||||||
imgStore, metaDB, log)
|
imgStore, metaDB, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
metadataSuccessfullySet = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !metadataSuccessfullySet {
|
|
||||||
log.Info().Str("tag", reference).Str("repository", repo).Msg("uploading image meta was unsuccessful for tag in repo")
|
log.Info().Str("tag", reference).Str("repository", repo).Msg("uploading image meta was unsuccessful for tag in repo")
|
||||||
|
|
||||||
if err := imgStore.DeleteImageManifest(repo, reference, false); err != nil {
|
if err := imgStore.DeleteImageManifest(repo, reference, false); err != nil {
|
||||||
@ -130,15 +84,6 @@ func OnDeleteManifest(repo, reference, mediaType string, digest godigest.Digest,
|
|||||||
|
|
||||||
manageRepoMetaSuccessfully = false
|
manageRepoMetaSuccessfully = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if referredDigest, hasSubject := common.GetReferredSubject(manifestBlob); hasSubject {
|
|
||||||
err := metaDB.DeleteReferrer(repo, referredDigest, digest)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Msg("metadb: error while deleting referrer")
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !manageRepoMetaSuccessfully {
|
if !manageRepoMetaSuccessfully {
|
||||||
@ -152,7 +97,7 @@ func OnDeleteManifest(repo, reference, mediaType string, digest godigest.Digest,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// OnDeleteManifest is called when a manifest is downloaded. It increments the download couter on that manifest.
|
// OnDeleteManifest is called when a manifest is downloaded. It increments the download couter on that manifest.
|
||||||
func OnGetManifest(name, reference string, body []byte,
|
func OnGetManifest(name, reference, mediaType string, body []byte,
|
||||||
storeController storage.StoreController, metaDB mTypes.MetaDB, log log.Logger,
|
storeController storage.StoreController, metaDB mTypes.MetaDB, log log.Logger,
|
||||||
) error {
|
) error {
|
||||||
// check if image is a signature
|
// check if image is a signature
|
||||||
@ -163,15 +108,21 @@ func OnGetManifest(name, reference string, body []byte,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isSignature && !zcommon.IsReferrersTag(reference) {
|
if isSignature || zcommon.IsReferrersTag(reference) {
|
||||||
err := metaDB.IncrementImageDownloads(name, reference)
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !(mediaType == v1.MediaTypeImageManifest || mediaType == v1.MediaTypeImageIndex) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err = metaDB.IncrementImageDownloads(name, reference)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Str("repository", name).Str("reference", reference).
|
log.Error().Err(err).Str("repository", name).Str("reference", reference).
|
||||||
Msg("unexpected error for image")
|
Msg("unexpected error for image")
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,19 @@
|
|||||||
package meta_test
|
package meta_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
notreg "github.com/notaryproject/notation-go/registry"
|
|
||||||
godigest "github.com/opencontainers/go-digest"
|
|
||||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
|
||||||
zerr "zotregistry.io/zot/errors"
|
|
||||||
"zotregistry.io/zot/pkg/extensions/monitoring"
|
"zotregistry.io/zot/pkg/extensions/monitoring"
|
||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
"zotregistry.io/zot/pkg/meta"
|
"zotregistry.io/zot/pkg/meta"
|
||||||
"zotregistry.io/zot/pkg/meta/boltdb"
|
"zotregistry.io/zot/pkg/meta/boltdb"
|
||||||
mTypes "zotregistry.io/zot/pkg/meta/types"
|
|
||||||
"zotregistry.io/zot/pkg/storage"
|
"zotregistry.io/zot/pkg/storage"
|
||||||
"zotregistry.io/zot/pkg/storage/local"
|
"zotregistry.io/zot/pkg/storage/local"
|
||||||
"zotregistry.io/zot/pkg/test/deprecated"
|
|
||||||
. "zotregistry.io/zot/pkg/test/image-utils"
|
. "zotregistry.io/zot/pkg/test/image-utils"
|
||||||
"zotregistry.io/zot/pkg/test/mocks"
|
"zotregistry.io/zot/pkg/test/mocks"
|
||||||
)
|
)
|
||||||
@ -42,259 +37,38 @@ func TestOnUpdateManifest(t *testing.T) {
|
|||||||
metaDB, err := boltdb.New(boltDriver, log)
|
metaDB, err := boltdb.New(boltDriver, log)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
config, layers, manifest, err := deprecated.GetRandomImageComponents(100) //nolint:staticcheck
|
image := CreateDefaultImage()
|
||||||
|
|
||||||
|
err = WriteImageToFileSystem(CreateDefaultImage(), "repo", "tag1", storeController)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
err = WriteImageToFileSystem(
|
err = meta.OnUpdateManifest("repo", "tag1", ispec.MediaTypeImageManifest, image.Digest(),
|
||||||
Image{
|
image.ManifestDescriptor.Data, storeController, metaDB, log)
|
||||||
Config: config, Manifest: manifest, Layers: layers,
|
|
||||||
}, "repo", "tag1", storeController)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
manifestBlob, err := json.Marshal(manifest)
|
repoMeta, err := metaDB.GetRepoMeta(context.Background(), "repo")
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
digest := godigest.FromBytes(manifestBlob)
|
|
||||||
|
|
||||||
err = meta.OnUpdateManifest("repo", "tag1", "", digest, manifestBlob, storeController, metaDB, log)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
repoMeta, err := metaDB.GetRepoMeta("repo")
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
So(repoMeta.Tags, ShouldContainKey, "tag1")
|
So(repoMeta.Tags, ShouldContainKey, "tag1")
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("metadataSuccessfullySet is false", t, func() {
|
|
||||||
rootDir := t.TempDir()
|
|
||||||
storeController := storage.StoreController{}
|
|
||||||
log := log.NewLogger("debug", "")
|
|
||||||
metrics := monitoring.NewMetricsServer(false, log)
|
|
||||||
storeController.DefaultStore = local.NewImageStore(rootDir, true, true, log, metrics, nil, nil)
|
|
||||||
|
|
||||||
metaDB := mocks.MetaDBMock{
|
|
||||||
SetManifestDataFn: func(manifestDigest godigest.Digest, mm mTypes.ManifestData) error {
|
|
||||||
return ErrTestError
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err := meta.OnUpdateManifest("repo", "tag1", ispec.MediaTypeImageManifest, "digest",
|
|
||||||
[]byte("{}"), storeController, metaDB, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateErrors(t *testing.T) {
|
func TestUpdateErrors(t *testing.T) {
|
||||||
Convey("Update operations", t, func() {
|
Convey("Update operations", t, func() {
|
||||||
Convey("On UpdateManifest", func() {
|
|
||||||
imageStore := mocks.MockedImageStore{}
|
imageStore := mocks.MockedImageStore{}
|
||||||
storeController := storage.StoreController{DefaultStore: &imageStore}
|
storeController := storage.StoreController{DefaultStore: &imageStore}
|
||||||
metaDB := mocks.MetaDBMock{}
|
metaDB := mocks.MetaDBMock{}
|
||||||
log := log.NewLogger("debug", "")
|
log := log.NewLogger("debug", "")
|
||||||
|
|
||||||
Convey("CheckIsImageSignature errors", func() {
|
Convey("IsReferrersTag true update", func() {
|
||||||
badManifestBlob := []byte("bad")
|
|
||||||
|
|
||||||
imageStore.GetImageManifestFn = func(repo, reference string) ([]byte, godigest.Digest, string, error) {
|
|
||||||
return []byte{}, "", "", zerr.ErrManifestNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
imageStore.DeleteImageManifestFn = func(repo, reference string, detectCollision bool) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err := meta.OnUpdateManifest("repo", "tag1", "digest", "media", badManifestBlob,
|
|
||||||
storeController, metaDB, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("IsReferrersTag true", func() {
|
|
||||||
err := meta.OnUpdateManifest("repo", "sha256-123", "digest", "media", []byte("bad"),
|
err := meta.OnUpdateManifest("repo", "sha256-123", "digest", "media", []byte("bad"),
|
||||||
storeController, metaDB, log)
|
storeController, metaDB, log)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
})
|
})
|
||||||
|
Convey("IsReferrersTag true delete", func() {
|
||||||
Convey("GetSignatureLayersInfo errors", func() {
|
|
||||||
// get notation signature layers info
|
|
||||||
badNotationManifestContent := ispec.Manifest{
|
|
||||||
Subject: &ispec.Descriptor{
|
|
||||||
Digest: "123",
|
|
||||||
},
|
|
||||||
Config: ispec.Descriptor{MediaType: notreg.ArtifactTypeNotation},
|
|
||||||
}
|
|
||||||
|
|
||||||
badNotationManifestBlob, err := json.Marshal(badNotationManifestContent)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
imageStore.GetImageManifestFn = func(repo, reference string) ([]byte, godigest.Digest, string, error) {
|
|
||||||
return badNotationManifestBlob, "", "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err = meta.OnUpdateManifest("repo", "tag1", "", "digest", badNotationManifestBlob,
|
|
||||||
storeController, metaDB, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("UpdateSignaturesValidity", func() {
|
|
||||||
notationManifestContent := ispec.Manifest{
|
|
||||||
Subject: &ispec.Descriptor{
|
|
||||||
Digest: "123",
|
|
||||||
},
|
|
||||||
Config: ispec.Descriptor{MediaType: notreg.ArtifactTypeNotation},
|
|
||||||
Layers: []ispec.Descriptor{{
|
|
||||||
MediaType: ispec.MediaTypeImageLayer,
|
|
||||||
Digest: godigest.FromString("blob digest"),
|
|
||||||
}},
|
|
||||||
}
|
|
||||||
|
|
||||||
notationManifestBlob, err := json.Marshal(notationManifestContent)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
imageStore.GetImageManifestFn = func(repo, reference string) ([]byte, godigest.Digest, string, error) {
|
|
||||||
return notationManifestBlob, "", "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
imageStore.GetBlobContentFn = func(repo string, digest godigest.Digest) ([]byte, error) {
|
|
||||||
return []byte{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
metaDB.UpdateSignaturesValidityFn = func(repo string, manifestDigest godigest.Digest) error {
|
|
||||||
return ErrTestError
|
|
||||||
}
|
|
||||||
|
|
||||||
err = meta.OnUpdateManifest("repo", "tag1", "", "digest", notationManifestBlob,
|
|
||||||
storeController, metaDB, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("On DeleteManifest", func() {
|
|
||||||
imageStore := mocks.MockedImageStore{}
|
|
||||||
storeController := storage.StoreController{DefaultStore: &imageStore}
|
|
||||||
metaDB := mocks.MetaDBMock{}
|
|
||||||
log := log.NewLogger("debug", "")
|
|
||||||
|
|
||||||
Convey("CheckIsImageSignature errors", func() {
|
|
||||||
badManifestBlob := []byte("bad")
|
|
||||||
|
|
||||||
imageStore.GetImageManifestFn = func(repo, reference string) ([]byte, godigest.Digest, string, error) {
|
|
||||||
return []byte{}, "", "", zerr.ErrManifestNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
err := meta.OnDeleteManifest("repo", "tag1", "digest", "media", badManifestBlob,
|
|
||||||
storeController, metaDB, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("IsReferrersTag true", func() {
|
|
||||||
err := meta.OnDeleteManifest("repo", "sha256-123", "digest", "media", []byte("bad"),
|
err := meta.OnDeleteManifest("repo", "sha256-123", "digest", "media", []byte("bad"),
|
||||||
storeController, metaDB, log)
|
storeController, metaDB, log)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("DeleteReferrers errors", func() {
|
|
||||||
metaDB.DeleteReferrerFn = func(repo string, referredDigest, referrerDigest godigest.Digest) error {
|
|
||||||
return ErrTestError
|
|
||||||
}
|
|
||||||
|
|
||||||
err := meta.OnDeleteManifest("repo", "tag1", "digest", "media",
|
|
||||||
[]byte(`{"subject": {"digest": "dig"}}`),
|
|
||||||
storeController, metaDB, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("On GetManifest", func() {
|
|
||||||
imageStore := mocks.MockedImageStore{}
|
|
||||||
storeController := storage.StoreController{DefaultStore: &imageStore}
|
|
||||||
metaDB := mocks.MetaDBMock{}
|
|
||||||
log := log.NewLogger("debug", "")
|
|
||||||
|
|
||||||
Convey("CheckIsImageSignature errors", func() {
|
|
||||||
badManifestBlob := []byte("bad")
|
|
||||||
|
|
||||||
imageStore.GetImageManifestFn = func(repo, reference string) ([]byte, godigest.Digest, string, error) {
|
|
||||||
return []byte{}, "", "", zerr.ErrManifestNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
err := meta.OnGetManifest("repo", "tag1", badManifestBlob,
|
|
||||||
storeController, metaDB, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SetImageMetaFromInput", func() {
|
|
||||||
imageStore := mocks.MockedImageStore{}
|
|
||||||
metaDB := mocks.MetaDBMock{}
|
|
||||||
log := log.NewLogger("debug", "")
|
|
||||||
|
|
||||||
err := meta.SetImageMetaFromInput("repo", "ref", ispec.MediaTypeImageManifest, "digest",
|
|
||||||
[]byte("BadManifestBlob"), imageStore, metaDB, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
// reference is digest
|
|
||||||
|
|
||||||
manifestContent := ispec.Manifest{}
|
|
||||||
manifestBlob, err := json.Marshal(manifestContent)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
imageStore.GetImageManifestFn = func(repo, reference string) ([]byte, godigest.Digest, string, error) {
|
|
||||||
return manifestBlob, "", "", nil
|
|
||||||
}
|
|
||||||
imageStore.GetBlobContentFn = func(repo string, digest godigest.Digest) ([]byte, error) {
|
|
||||||
return []byte("{}"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err = meta.SetImageMetaFromInput("repo", string(godigest.FromString("reference")), "", "digest",
|
|
||||||
manifestBlob, imageStore, metaDB, log)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SetImageMetaFromInput SetData errors", func() {
|
|
||||||
imageStore := mocks.MockedImageStore{}
|
|
||||||
log := log.NewLogger("debug", "")
|
|
||||||
|
|
||||||
metaDB := mocks.MetaDBMock{
|
|
||||||
SetManifestDataFn: func(manifestDigest godigest.Digest, mm mTypes.ManifestData) error {
|
|
||||||
return ErrTestError
|
|
||||||
},
|
|
||||||
}
|
|
||||||
err := meta.SetImageMetaFromInput("repo", "ref", ispec.MediaTypeImageManifest, "digest",
|
|
||||||
[]byte("{}"), imageStore, metaDB, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SetImageMetaFromInput SetIndexData errors", func() {
|
|
||||||
imageStore := mocks.MockedImageStore{}
|
|
||||||
log := log.NewLogger("debug", "")
|
|
||||||
|
|
||||||
metaDB := mocks.MetaDBMock{
|
|
||||||
SetIndexDataFn: func(digest godigest.Digest, indexData mTypes.IndexData) error {
|
|
||||||
return ErrTestError
|
|
||||||
},
|
|
||||||
}
|
|
||||||
err := meta.SetImageMetaFromInput("repo", "ref", ispec.MediaTypeImageIndex, "digest",
|
|
||||||
[]byte("{}"), imageStore, metaDB, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("SetImageMetaFromInput SetReferrer errors", func() {
|
|
||||||
imageStore := mocks.MockedImageStore{
|
|
||||||
GetBlobContentFn: func(repo string, digest godigest.Digest) ([]byte, error) {
|
|
||||||
return []byte("{}"), nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
log := log.NewLogger("debug", "")
|
|
||||||
|
|
||||||
metaDB := mocks.MetaDBMock{
|
|
||||||
SetReferrerFn: func(repo string, referredDigest godigest.Digest, referrer mTypes.ReferrerInfo) error {
|
|
||||||
return ErrTestError
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err := meta.SetImageMetaFromInput("repo", "ref", ispec.MediaTypeImageManifest, "digest",
|
|
||||||
[]byte(`{"subject": {"digest": "subjDigest"}}`), imageStore, metaDB, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -81,10 +81,10 @@ func getDynamoParams(cacheDriverConfig map[string]interface{}, log log.Logger) m
|
|||||||
repoMetaTablename, ok := toStringIfOk(cacheDriverConfig, "repometatablename", log)
|
repoMetaTablename, ok := toStringIfOk(cacheDriverConfig, "repometatablename", log)
|
||||||
allParametersOk = allParametersOk && ok
|
allParametersOk = allParametersOk && ok
|
||||||
|
|
||||||
manifestDataTablename, ok := toStringIfOk(cacheDriverConfig, "manifestdatatablename", log)
|
repoBlobsInfoTablename, ok := toStringIfOk(cacheDriverConfig, "repoblobsinfotablename", log)
|
||||||
allParametersOk = allParametersOk && ok
|
allParametersOk = allParametersOk && ok
|
||||||
|
|
||||||
indexDataTablename, ok := toStringIfOk(cacheDriverConfig, "indexdatatablename", log)
|
imageMetaTablename, ok := toStringIfOk(cacheDriverConfig, "imagemetatablename", log)
|
||||||
allParametersOk = allParametersOk && ok
|
allParametersOk = allParametersOk && ok
|
||||||
|
|
||||||
apiKeyTablename, ok := toStringIfOk(cacheDriverConfig, "apikeytablename", log)
|
apiKeyTablename, ok := toStringIfOk(cacheDriverConfig, "apikeytablename", log)
|
||||||
@ -104,8 +104,8 @@ func getDynamoParams(cacheDriverConfig map[string]interface{}, log log.Logger) m
|
|||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
Region: region,
|
Region: region,
|
||||||
RepoMetaTablename: repoMetaTablename,
|
RepoMetaTablename: repoMetaTablename,
|
||||||
ManifestDataTablename: manifestDataTablename,
|
RepoBlobsInfoTablename: repoBlobsInfoTablename,
|
||||||
IndexDataTablename: indexDataTablename,
|
ImageMetaTablename: imageMetaTablename,
|
||||||
UserDataTablename: userDataTablename,
|
UserDataTablename: userDataTablename,
|
||||||
APIKeyTablename: apiKeyTablename,
|
APIKeyTablename: apiKeyTablename,
|
||||||
VersionTablename: versionTablename,
|
VersionTablename: versionTablename,
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,6 @@ package meta
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
godigest "github.com/opencontainers/go-digest"
|
godigest "github.com/opencontainers/go-digest"
|
||||||
@ -12,11 +11,17 @@ import (
|
|||||||
zerr "zotregistry.io/zot/errors"
|
zerr "zotregistry.io/zot/errors"
|
||||||
zcommon "zotregistry.io/zot/pkg/common"
|
zcommon "zotregistry.io/zot/pkg/common"
|
||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
|
"zotregistry.io/zot/pkg/meta/convert"
|
||||||
mTypes "zotregistry.io/zot/pkg/meta/types"
|
mTypes "zotregistry.io/zot/pkg/meta/types"
|
||||||
"zotregistry.io/zot/pkg/storage"
|
"zotregistry.io/zot/pkg/storage"
|
||||||
storageTypes "zotregistry.io/zot/pkg/storage/types"
|
storageTypes "zotregistry.io/zot/pkg/storage/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
CosignType = "cosign"
|
||||||
|
NotationType = "notation"
|
||||||
|
)
|
||||||
|
|
||||||
// ParseStorage will sync all repos found in the rootdirectory of the oci layout that zot was deployed on with the
|
// ParseStorage will sync all repos found in the rootdirectory of the oci layout that zot was deployed on with the
|
||||||
// ParseStorage database.
|
// ParseStorage database.
|
||||||
func ParseStorage(metaDB mTypes.MetaDB, storeController storage.StoreController, log log.Logger) error {
|
func ParseStorage(metaDB mTypes.MetaDB, storeController storage.StoreController, log log.Logger) error {
|
||||||
@ -31,7 +36,10 @@ func ParseStorage(metaDB mTypes.MetaDB, storeController storage.StoreController,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, repo := range allRepos {
|
for i, repo := range allRepos {
|
||||||
|
log.Info().Int("total", len(allRepos)).Int("progress", i).Str("current-repo", repo).
|
||||||
|
Msgf("parsing next repo '%s'", repo)
|
||||||
|
|
||||||
err := ParseRepo(repo, metaDB, storeController, log)
|
err := ParseRepo(repo, metaDB, storeController, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Str("repository", repo).Msg("load-local-layout: failed to sync repo")
|
log.Error().Err(err).Str("repository", repo).Msg("load-local-layout: failed to sync repo")
|
||||||
@ -70,75 +78,35 @@ func ParseRepo(repo string, metaDB mTypes.MetaDB, storeController storage.StoreC
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = resetRepoMeta(repo, metaDB, log)
|
err = metaDB.ResetRepoReferences(repo)
|
||||||
if err != nil && !errors.Is(err, zerr.ErrRepoMetaNotFound) {
|
if err != nil && !errors.Is(err, zerr.ErrRepoMetaNotFound) {
|
||||||
log.Error().Err(err).Str("repository", repo).Msg("load-repo: failed to reset tag field in RepoMetadata for repo")
|
log.Error().Err(err).Str("repository", repo).Msg("load-repo: failed to reset tag field in RepoMetadata for repo")
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, descriptor := range indexContent.Manifests {
|
for _, manifest := range indexContent.Manifests {
|
||||||
tag := descriptor.Annotations[ispec.AnnotationRefName]
|
tag := manifest.Annotations[ispec.AnnotationRefName]
|
||||||
|
|
||||||
if zcommon.IsReferrersTag(tag) {
|
if zcommon.IsReferrersTag(tag) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptorBlob, err := getCachedBlob(repo, descriptor, metaDB, imageStore, log)
|
manifestBlob, _, _, err := imageStore.GetImageManifest(repo, manifest.Digest.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("load-repo: error checking manifestMeta in MetaDB")
|
log.Error().Err(err).Str("repository", repo).Str("digest", manifest.Digest.String()).
|
||||||
|
Msg("load-repo: failed to get blob for image")
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
isSignature, signatureType, signedManifestDigest, err := storage.CheckIsImageSignature(repo,
|
|
||||||
descriptorBlob, tag)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Str("repository", repo).Str("tag", tag).
|
|
||||||
Msg("load-repo: failed checking if image is signature for specified image")
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if isSignature {
|
|
||||||
layers, err := GetSignatureLayersInfo(repo, tag, descriptor.Digest.String(), signatureType,
|
|
||||||
descriptorBlob, imageStore, log)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.AddManifestSignature(repo, signedManifestDigest,
|
|
||||||
mTypes.SignatureMetadata{
|
|
||||||
SignatureType: signatureType,
|
|
||||||
SignatureDigest: descriptor.Digest.String(),
|
|
||||||
LayersInfo: layers,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Str("repository", repo).Str("tag", tag).
|
|
||||||
Str("manifestDigest", signedManifestDigest.String()).
|
|
||||||
Msg("load-repo: failed set signature meta for signed image")
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.UpdateSignaturesValidity(repo, signedManifestDigest)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Str("repository", repo).Str("reference", tag).Str("digest", signedManifestDigest.String()).Msg(
|
|
||||||
"load-repo: failed verify signatures validity for signed image")
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
reference := tag
|
reference := tag
|
||||||
|
|
||||||
if tag == "" {
|
if tag == "" {
|
||||||
reference = descriptor.Digest.String()
|
reference = manifest.Digest.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
err = SetImageMetaFromInput(repo, reference, descriptor.MediaType, descriptor.Digest, descriptorBlob,
|
err = SetImageMetaFromInput(repo, reference, manifest.MediaType, manifest.Digest, manifestBlob,
|
||||||
imageStore, metaDB, log)
|
imageStore, metaDB, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Str("repository", repo).Str("tag", tag).
|
log.Error().Err(err).Str("repository", repo).Str("tag", tag).
|
||||||
@ -151,32 +119,6 @@ func ParseRepo(repo string, metaDB mTypes.MetaDB, storeController storage.StoreC
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// resetRepoMeta will delete all tags and non-user related information from a RepoMetadata.
|
|
||||||
// It is used to recalculate and keep MetaDB consistent with the layout in case of unexpected changes.
|
|
||||||
func resetRepoMeta(repo string, metaDB mTypes.MetaDB, log log.Logger) error {
|
|
||||||
repoMeta, err := metaDB.GetRepoMeta(repo)
|
|
||||||
if err != nil && !errors.Is(err, zerr.ErrRepoMetaNotFound) {
|
|
||||||
log.Error().Err(err).Str("repository", repo).Msg("load-repo: failed to get RepoMeta for repo")
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if errors.Is(err, zerr.ErrRepoMetaNotFound) {
|
|
||||||
log.Info().Str("repository", repo).Msg("load-repo: RepoMeta not found for repo, new RepoMeta will be created")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return metaDB.SetRepoMeta(repo, mTypes.RepoMetadata{
|
|
||||||
Name: repoMeta.Name,
|
|
||||||
Tags: map[string]mTypes.Descriptor{},
|
|
||||||
Statistics: repoMeta.Statistics,
|
|
||||||
Signatures: map[string]mTypes.ManifestSignatures{},
|
|
||||||
Referrers: map[string][]mTypes.ReferrerInfo{},
|
|
||||||
Stars: repoMeta.Stars,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAllRepos(storeController storage.StoreController) ([]string, error) {
|
func getAllRepos(storeController storage.StoreController) ([]string, error) {
|
||||||
allRepos, err := storeController.DefaultStore.GetRepositories()
|
allRepos, err := storeController.DefaultStore.GetRepositories()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -197,43 +139,6 @@ func getAllRepos(storeController storage.StoreController) ([]string, error) {
|
|||||||
return allRepos, nil
|
return allRepos, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCachedBlob(repo string, descriptor ispec.Descriptor, metaDB mTypes.MetaDB,
|
|
||||||
imageStore storageTypes.ImageStore, log log.Logger,
|
|
||||||
) ([]byte, error) {
|
|
||||||
digest := descriptor.Digest
|
|
||||||
|
|
||||||
descriptorBlob, err := getCachedBlobFromMetaDB(descriptor, metaDB)
|
|
||||||
|
|
||||||
if err != nil || len(descriptorBlob) == 0 {
|
|
||||||
descriptorBlob, _, _, err = imageStore.GetImageManifest(repo, digest.String())
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Str("repository", repo).Str("digest", digest.String()).
|
|
||||||
Msg("load-repo: failed to get blob for image")
|
|
||||||
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return descriptorBlob, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return descriptorBlob, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCachedBlobFromMetaDB(descriptor ispec.Descriptor, metaDB mTypes.MetaDB) ([]byte, error) {
|
|
||||||
switch descriptor.MediaType {
|
|
||||||
case ispec.MediaTypeImageManifest:
|
|
||||||
manifestData, err := metaDB.GetManifestData(descriptor.Digest)
|
|
||||||
|
|
||||||
return manifestData.ManifestBlob, err
|
|
||||||
case ispec.MediaTypeImageIndex:
|
|
||||||
indexData, err := metaDB.GetIndexData(descriptor.Digest)
|
|
||||||
|
|
||||||
return indexData.IndexBlob, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetSignatureLayersInfo(repo, tag, manifestDigest, signatureType string, manifestBlob []byte,
|
func GetSignatureLayersInfo(repo, tag, manifestDigest, signatureType string, manifestBlob []byte,
|
||||||
imageStore storageTypes.ImageStore, log log.Logger,
|
imageStore storageTypes.ImageStore, log log.Logger,
|
||||||
) ([]mTypes.LayerInfo, error) {
|
) ([]mTypes.LayerInfo, error) {
|
||||||
@ -341,92 +246,82 @@ func getNotationSignatureLayersInfo(
|
|||||||
return layers, nil
|
return layers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewManifestMeta takes raw data about an image and createa a new ManifestMetadate object.
|
// SetMetadataFromInput tries to set manifest metadata and update repo metadata by adding the current tag
|
||||||
func NewManifestData(repoName string, manifestBlob []byte, imageStore storageTypes.ImageStore,
|
// (in case the reference is a tag). The function expects image manifests and indexes (multi arch images).
|
||||||
) (mTypes.ManifestData, error) {
|
func SetImageMetaFromInput(repo, reference, mediaType string, digest godigest.Digest, blob []byte,
|
||||||
var (
|
imageStore storageTypes.ImageStore, metaDB mTypes.MetaDB, log log.Logger,
|
||||||
manifestContent ispec.Manifest
|
) error {
|
||||||
configContent ispec.Image
|
var imageMeta mTypes.ImageMeta
|
||||||
manifestData mTypes.ManifestData
|
|
||||||
)
|
|
||||||
|
|
||||||
err := json.Unmarshal(manifestBlob, &manifestContent)
|
switch mediaType {
|
||||||
|
case ispec.MediaTypeImageManifest:
|
||||||
|
manifestContent := ispec.Manifest{}
|
||||||
|
configContent := ispec.Image{}
|
||||||
|
|
||||||
|
err := json.Unmarshal(blob, &manifestContent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mTypes.ManifestData{}, err
|
return err
|
||||||
}
|
|
||||||
|
|
||||||
var lockLatency time.Time
|
|
||||||
|
|
||||||
imageStore.RLock(&lockLatency)
|
|
||||||
defer imageStore.RUnlock(&lockLatency)
|
|
||||||
|
|
||||||
configBlob, err := imageStore.GetBlobContent(repoName, manifestContent.Config.Digest)
|
|
||||||
if err != nil {
|
|
||||||
return mTypes.ManifestData{}, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if manifestContent.Config.MediaType == ispec.MediaTypeImageConfig {
|
if manifestContent.Config.MediaType == ispec.MediaTypeImageConfig {
|
||||||
|
configBlob, err := imageStore.GetBlobContent(repo, manifestContent.Config.Digest)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
err = json.Unmarshal(configBlob, &configContent)
|
err = json.Unmarshal(configBlob, &configContent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mTypes.ManifestData{}, err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
manifestData.ManifestBlob = manifestBlob
|
if isSig, sigType, signedManifestDigest := isSignature(reference, manifestContent); isSig {
|
||||||
manifestData.ConfigBlob = configBlob
|
layers, err := GetSignatureLayersInfo(repo, reference, digest.String(), sigType,
|
||||||
|
blob, imageStore, log)
|
||||||
return manifestData, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewIndexData(repoName string, indexBlob []byte, imageStore storageTypes.ImageStore,
|
|
||||||
) mTypes.IndexData {
|
|
||||||
indexData := mTypes.IndexData{}
|
|
||||||
|
|
||||||
indexData.IndexBlob = indexBlob
|
|
||||||
|
|
||||||
return indexData
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetMetadataFromInput tries to set manifest metadata and update repo metadata by adding the current tag
|
|
||||||
// (in case the reference is a tag). The function expects image manifests and indexes (multi arch images).
|
|
||||||
func SetImageMetaFromInput(repo, reference, mediaType string, digest godigest.Digest, descriptorBlob []byte,
|
|
||||||
imageStore storageTypes.ImageStore, metaDB mTypes.MetaDB, log log.Logger,
|
|
||||||
) error {
|
|
||||||
switch mediaType {
|
|
||||||
case ispec.MediaTypeImageManifest:
|
|
||||||
imageData, err := NewManifestData(repo, descriptorBlob, imageStore)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = metaDB.SetManifestData(digest, imageData)
|
err = metaDB.AddManifestSignature(repo, signedManifestDigest,
|
||||||
|
mTypes.SignatureMetadata{
|
||||||
|
SignatureType: sigType,
|
||||||
|
SignatureDigest: digest.String(),
|
||||||
|
LayersInfo: layers,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("metadb: error while putting manifest meta")
|
log.Error().Err(err).Str("repository", repo).Str("tag", reference).
|
||||||
|
Str("manifestDigest", signedManifestDigest.String()).
|
||||||
|
Msg("load-repo: failed set signature meta for signed image")
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = metaDB.UpdateSignaturesValidity(repo, signedManifestDigest)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Str("repository", repo).Str("reference", reference).Str("digest",
|
||||||
|
signedManifestDigest.String()).Msg("load-repo: failed verify signatures validity for signed image")
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
imageMeta = convert.GetImageManifestMeta(manifestContent, configContent, int64(len(blob)), digest)
|
||||||
case ispec.MediaTypeImageIndex:
|
case ispec.MediaTypeImageIndex:
|
||||||
indexData := NewIndexData(repo, descriptorBlob, imageStore)
|
indexContent := ispec.Index{}
|
||||||
|
|
||||||
err := metaDB.SetIndexData(digest, indexData)
|
err := json.Unmarshal(blob, &indexContent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("metadb: error while putting index data")
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
imageMeta = convert.GetImageIndexMeta(indexContent, int64(len(blob)), digest)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
referredDigest, referrerInfo, hasSubject, err := GetReferredInfo(descriptorBlob, digest.String(), mediaType)
|
err := metaDB.SetRepoReference(repo, reference, imageMeta)
|
||||||
if hasSubject && err == nil {
|
|
||||||
err := metaDB.SetReferrer(repo, referredDigest, referrerInfo)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Msg("metadb: error while settingg referrer")
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = metaDB.SetRepoReference(repo, reference, digest, mediaType)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("metadb: error while putting repo meta")
|
log.Error().Err(err).Msg("metadb: error while putting repo meta")
|
||||||
|
|
||||||
@ -436,55 +331,24 @@ func SetImageMetaFromInput(repo, reference, mediaType string, digest godigest.Di
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetReferredInfo(descriptorBlob []byte, referrerDigest, mediaType string,
|
func isSignature(reference string, manifestContent ispec.Manifest) (bool, string, godigest.Digest) {
|
||||||
) (godigest.Digest, mTypes.ReferrerInfo, bool, error) {
|
manifestArtifactType := zcommon.GetManifestArtifactType(manifestContent)
|
||||||
var (
|
|
||||||
referrerInfo mTypes.ReferrerInfo
|
|
||||||
referrerSubject *ispec.Descriptor
|
|
||||||
)
|
|
||||||
|
|
||||||
switch mediaType {
|
// check notation signature
|
||||||
case ispec.MediaTypeImageManifest:
|
if manifestArtifactType == zcommon.ArtifactTypeNotation && manifestContent.Subject != nil {
|
||||||
var manifestContent ispec.Manifest
|
return true, NotationType, manifestContent.Subject.Digest
|
||||||
|
|
||||||
err := json.Unmarshal(descriptorBlob, &manifestContent)
|
|
||||||
if err != nil {
|
|
||||||
return "", referrerInfo, false,
|
|
||||||
fmt.Errorf("metadb: can't unmarshal manifest for digest %s: %w", referrerDigest, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
referrerSubject = manifestContent.Subject
|
if tag := reference; zcommon.IsCosignTag(reference) {
|
||||||
|
prefixLen := len("sha256-")
|
||||||
|
digestLen := 64
|
||||||
|
signedImageManifestDigestEncoded := tag[prefixLen : prefixLen+digestLen]
|
||||||
|
|
||||||
referrerInfo = mTypes.ReferrerInfo{
|
signedImageManifestDigest := godigest.NewDigestFromEncoded(godigest.SHA256,
|
||||||
Digest: referrerDigest,
|
signedImageManifestDigestEncoded)
|
||||||
MediaType: mediaType,
|
|
||||||
ArtifactType: zcommon.GetManifestArtifactType(manifestContent),
|
|
||||||
Size: len(descriptorBlob),
|
|
||||||
Annotations: manifestContent.Annotations,
|
|
||||||
}
|
|
||||||
case ispec.MediaTypeImageIndex:
|
|
||||||
var indexContent ispec.Index
|
|
||||||
|
|
||||||
err := json.Unmarshal(descriptorBlob, &indexContent)
|
return true, CosignType, signedImageManifestDigest
|
||||||
if err != nil {
|
|
||||||
return "", referrerInfo, false,
|
|
||||||
fmt.Errorf("metadb: can't unmarshal manifest for digest %s: %w", referrerDigest, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
referrerSubject = indexContent.Subject
|
return false, "", ""
|
||||||
|
|
||||||
referrerInfo = mTypes.ReferrerInfo{
|
|
||||||
Digest: referrerDigest,
|
|
||||||
MediaType: mediaType,
|
|
||||||
ArtifactType: zcommon.GetIndexArtifactType(indexContent),
|
|
||||||
Size: len(descriptorBlob),
|
|
||||||
Annotations: indexContent.Annotations,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if referrerSubject == nil || referrerSubject.Digest.String() == "" {
|
|
||||||
return "", mTypes.ReferrerInfo{}, false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return referrerSubject.Digest, referrerInfo, true, nil
|
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ import (
|
|||||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
|
||||||
zerr "zotregistry.io/zot/errors"
|
|
||||||
zcommon "zotregistry.io/zot/pkg/common"
|
zcommon "zotregistry.io/zot/pkg/common"
|
||||||
"zotregistry.io/zot/pkg/extensions/monitoring"
|
"zotregistry.io/zot/pkg/extensions/monitoring"
|
||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
@ -97,50 +96,6 @@ func TestParseStorageErrors(t *testing.T) {
|
|||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("resetRepoMetaTags errors", func() {
|
|
||||||
imageStore.GetIndexContentFn = func(repo string) ([]byte, error) {
|
|
||||||
return []byte("{}"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
Convey("metaDB.GetRepoMeta errors", func() {
|
|
||||||
metaDB.GetRepoMetaFn = func(repo string) (mTypes.RepoMetadata, error) {
|
|
||||||
return mTypes.RepoMetadata{}, ErrTestError
|
|
||||||
}
|
|
||||||
|
|
||||||
err := meta.ParseRepo("repo", metaDB, storeController, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("isManifestMetaPresent errors", func() {
|
|
||||||
indexContent := ispec.Index{
|
|
||||||
Manifests: []ispec.Descriptor{
|
|
||||||
{
|
|
||||||
Digest: godigest.FromString("manifest1"),
|
|
||||||
MediaType: ispec.MediaTypeImageManifest,
|
|
||||||
Annotations: map[string]string{
|
|
||||||
ispec.AnnotationRefName: "tag1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
indexBlob, err := json.Marshal(indexContent)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
imageStore.GetIndexContentFn = func(repo string) ([]byte, error) {
|
|
||||||
return indexBlob, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
Convey("metaDB.GetManifestMeta errors", func() {
|
|
||||||
metaDB.GetManifestMetaFn = func(repo string, manifestDigest godigest.Digest) (mTypes.ManifestMetadata, error) {
|
|
||||||
return mTypes.ManifestMetadata{}, ErrTestError
|
|
||||||
}
|
|
||||||
|
|
||||||
err = meta.ParseRepo("repo", metaDB, storeController, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("manifestMetaIsPresent true", func() {
|
Convey("manifestMetaIsPresent true", func() {
|
||||||
indexContent := ispec.Index{
|
indexContent := ispec.Index{
|
||||||
Manifests: []ispec.Descriptor{
|
Manifests: []ispec.Descriptor{
|
||||||
@ -161,7 +116,7 @@ func TestParseStorageErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Convey("metaDB.SetRepoReference", func() {
|
Convey("metaDB.SetRepoReference", func() {
|
||||||
metaDB.SetRepoReferenceFn = func(repo, tag string, manifestDigest godigest.Digest, mediaType string) error {
|
metaDB.SetRepoReferenceFn = func(repo, reference string, imageMeta mTypes.ImageMeta) error {
|
||||||
return ErrTestError
|
return ErrTestError
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,212 +124,6 @@ func TestParseStorageErrors(t *testing.T) {
|
|||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("manifestMetaIsPresent false", func() {
|
|
||||||
indexContent := ispec.Index{
|
|
||||||
Manifests: []ispec.Descriptor{
|
|
||||||
{
|
|
||||||
Digest: godigest.FromString("manifest1"),
|
|
||||||
MediaType: ispec.MediaTypeImageManifest,
|
|
||||||
Annotations: map[string]string{
|
|
||||||
ispec.AnnotationRefName: "tag1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
indexBlob, err := json.Marshal(indexContent)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
imageStore.GetIndexContentFn = func(repo string) ([]byte, error) {
|
|
||||||
return indexBlob, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
metaDB.GetManifestMetaFn = func(repo string, manifestDigest godigest.Digest) (mTypes.ManifestMetadata, error) {
|
|
||||||
return mTypes.ManifestMetadata{}, zerr.ErrManifestMetaNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
Convey("GetImageManifest errors", func() {
|
|
||||||
imageStore.GetImageManifestFn = func(repo, reference string) ([]byte, godigest.Digest, string, error) {
|
|
||||||
return nil, "", "", ErrTestError
|
|
||||||
}
|
|
||||||
err = meta.ParseRepo("repo", metaDB, storeController, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("CheckIsImageSignature errors", func() {
|
|
||||||
// CheckIsImageSignature will fail because of a invalid json
|
|
||||||
imageStore.GetImageManifestFn = func(repo, reference string) ([]byte, godigest.Digest, string, error) {
|
|
||||||
return []byte("Invalid JSON"), "", "", nil
|
|
||||||
}
|
|
||||||
err = meta.ParseRepo("repo", metaDB, storeController, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
Convey("CheckIsImageSignature -> not signature", func() {
|
|
||||||
manifestContent := ispec.Manifest{}
|
|
||||||
manifestBlob, err := json.Marshal(manifestContent)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
imageStore.GetImageManifestFn = func(repo, reference string) ([]byte, godigest.Digest, string, error) {
|
|
||||||
return manifestBlob, "", "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
Convey("imgStore.GetBlobContent errors", func() {
|
|
||||||
imageStore.GetBlobContentFn = func(repo string, digest godigest.Digest) ([]byte, error) {
|
|
||||||
return nil, ErrTestError
|
|
||||||
}
|
|
||||||
|
|
||||||
err = meta.ParseRepo("repo", metaDB, storeController, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("CheckIsImageSignature -> is signature", func() {
|
|
||||||
manifestContent := ispec.Manifest{
|
|
||||||
Subject: &ispec.Descriptor{
|
|
||||||
Digest: "123",
|
|
||||||
},
|
|
||||||
ArtifactType: "application/vnd.cncf.notary.signature",
|
|
||||||
Layers: []ispec.Descriptor{{MediaType: ispec.MediaTypeImageLayer}},
|
|
||||||
}
|
|
||||||
|
|
||||||
manifestBlob, err := json.Marshal(manifestContent)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
imageStore.GetImageManifestFn = func(repo, reference string) ([]byte, godigest.Digest, string, error) {
|
|
||||||
return manifestBlob, "", "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
metaDB.AddManifestSignatureFn = func(repo string, signedManifestDigest godigest.Digest,
|
|
||||||
sm mTypes.SignatureMetadata,
|
|
||||||
) error {
|
|
||||||
return ErrTestError
|
|
||||||
}
|
|
||||||
|
|
||||||
err = meta.ParseRepo("repo", metaDB, storeController, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
metaDB.AddManifestSignatureFn = func(repo string, signedManifestDigest godigest.Digest,
|
|
||||||
sm mTypes.SignatureMetadata,
|
|
||||||
) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
metaDB.UpdateSignaturesValidityFn = func(repo string, signedManifestDigest godigest.Digest,
|
|
||||||
) error {
|
|
||||||
return ErrTestError
|
|
||||||
}
|
|
||||||
|
|
||||||
err = meta.ParseRepo("repo", metaDB, storeController, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("GetSignatureLayersInfo errors", func() {
|
|
||||||
// get notation signature layers info
|
|
||||||
badNotationManifestContent := ispec.Manifest{
|
|
||||||
Subject: &ispec.Descriptor{
|
|
||||||
Digest: "123",
|
|
||||||
},
|
|
||||||
ArtifactType: "application/vnd.cncf.notary.signature",
|
|
||||||
}
|
|
||||||
|
|
||||||
badNotationManifestBlob, err := json.Marshal(badNotationManifestContent)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
imageStore.GetImageManifestFn = func(repo, reference string) ([]byte, godigest.Digest, string, error) {
|
|
||||||
return badNotationManifestBlob, "", "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// wrong number of layers of notation manifest
|
|
||||||
err = meta.ParseRepo("repo", metaDB, storeController, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
notationManifestContent := ispec.Manifest{
|
|
||||||
Subject: &ispec.Descriptor{
|
|
||||||
Digest: "123",
|
|
||||||
},
|
|
||||||
ArtifactType: "application/vnd.cncf.notary.signature",
|
|
||||||
Layers: []ispec.Descriptor{{MediaType: ispec.MediaTypeImageLayer}},
|
|
||||||
}
|
|
||||||
|
|
||||||
notationManifestBlob, err := json.Marshal(notationManifestContent)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
imageStore.GetImageManifestFn = func(repo, reference string) ([]byte, godigest.Digest, string, error) {
|
|
||||||
return notationManifestBlob, "", "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
imageStore.GetBlobContentFn = func(repo string, digest godigest.Digest) ([]byte, error) {
|
|
||||||
return []byte{}, ErrTestError
|
|
||||||
}
|
|
||||||
|
|
||||||
// unable to get layer content
|
|
||||||
err = meta.ParseRepo("repo", metaDB, storeController, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
_, _, cosignManifestContent, _ := deprecated.GetRandomImageComponents(10) //nolint:staticcheck
|
|
||||||
_, _, signedManifest, _ := deprecated.GetRandomImageComponents(10) //nolint:staticcheck
|
|
||||||
signatureTag, err := signature.GetCosignSignatureTagForManifest(signedManifest)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
cosignManifestContent.Annotations = map[string]string{ispec.AnnotationRefName: signatureTag}
|
|
||||||
|
|
||||||
cosignManifestBlob, err := json.Marshal(cosignManifestContent)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
imageStore.GetImageManifestFn = func(repo, reference string) ([]byte, godigest.Digest, string, error) {
|
|
||||||
return cosignManifestBlob, "", "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
indexContent := ispec.Index{
|
|
||||||
Manifests: []ispec.Descriptor{
|
|
||||||
{
|
|
||||||
Digest: godigest.FromString("cosignSig"),
|
|
||||||
MediaType: ispec.MediaTypeImageManifest,
|
|
||||||
Annotations: map[string]string{
|
|
||||||
ispec.AnnotationRefName: signatureTag,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
indexBlob, err := json.Marshal(indexContent)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
imageStore.GetIndexContentFn = func(repo string) ([]byte, error) {
|
|
||||||
return indexBlob, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// unable to get layer content
|
|
||||||
err = meta.ParseRepo("repo", metaDB, storeController, log)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("IsReferrersTag -> true", func() {
|
|
||||||
indexContent := ispec.Index{
|
|
||||||
Manifests: []ispec.Descriptor{
|
|
||||||
{
|
|
||||||
Digest: godigest.FromString("indx1"),
|
|
||||||
MediaType: ispec.MediaTypeImageIndex,
|
|
||||||
Annotations: map[string]string{
|
|
||||||
ispec.AnnotationRefName: "sha256-123",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
indexBlob, err := json.Marshal(indexContent)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
imageStore.GetIndexContentFn = func(repo string) ([]byte, error) {
|
|
||||||
return indexBlob, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
metaDB.SetIndexDataFn = func(digest godigest.Digest, indexData mTypes.IndexData) error {
|
|
||||||
return ErrTestError
|
|
||||||
}
|
|
||||||
|
|
||||||
err = meta.ParseRepo("repo", metaDB, storeController, log)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,8 +153,8 @@ func TestParseStorageDynamoWrapper(t *testing.T) {
|
|||||||
Endpoint: os.Getenv("DYNAMODBMOCK_ENDPOINT"),
|
Endpoint: os.Getenv("DYNAMODBMOCK_ENDPOINT"),
|
||||||
Region: "us-east-2",
|
Region: "us-east-2",
|
||||||
RepoMetaTablename: "RepoMetadataTable",
|
RepoMetaTablename: "RepoMetadataTable",
|
||||||
ManifestDataTablename: "ManifestDataTable",
|
RepoBlobsInfoTablename: "RepoBlobsInfoTablename",
|
||||||
IndexDataTablename: "IndexDataTable",
|
ImageMetaTablename: "ImageMetaTablename",
|
||||||
UserDataTablename: "UserDataTable",
|
UserDataTablename: "UserDataTable",
|
||||||
APIKeyTablename: "ApiKeyTable",
|
APIKeyTablename: "ApiKeyTable",
|
||||||
VersionTablename: "Version",
|
VersionTablename: "Version",
|
||||||
@ -417,10 +166,13 @@ func TestParseStorageDynamoWrapper(t *testing.T) {
|
|||||||
dynamoWrapper, err := dynamodb.New(dynamoClient, params, log.NewLogger("debug", ""))
|
dynamoWrapper, err := dynamodb.New(dynamoClient, params, log.NewLogger("debug", ""))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
err = dynamoWrapper.ResetManifestDataTable()
|
err = dynamoWrapper.ResetTable(dynamoWrapper.RepoMetaTablename)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
err = dynamoWrapper.ResetRepoMetaTable()
|
err = dynamoWrapper.ResetTable(dynamoWrapper.RepoBlobsTablename)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
err = dynamoWrapper.ResetTable(dynamoWrapper.ImageMetaTablename)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
RunParseStorageTests(rootDir, dynamoWrapper)
|
RunParseStorageTests(rootDir, dynamoWrapper)
|
||||||
@ -496,20 +248,20 @@ func RunParseStorageTests(rootDir string, metaDB mTypes.MetaDB) {
|
|||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
repos, err := metaDB.GetMultipleRepoMeta(context.Background(),
|
repos, err := metaDB.GetMultipleRepoMeta(context.Background(),
|
||||||
func(repoMeta mTypes.RepoMetadata) bool { return true })
|
func(repoMeta mTypes.RepoMeta) bool { return true })
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
So(len(repos), ShouldEqual, 1)
|
So(len(repos), ShouldEqual, 1)
|
||||||
So(len(repos[0].Tags), ShouldEqual, 2)
|
So(len(repos[0].Tags), ShouldEqual, 2)
|
||||||
|
|
||||||
for _, descriptor := range repos[0].Tags {
|
ctx := context.Background()
|
||||||
manifestMeta, err := metaDB.GetManifestMeta(repo, godigest.Digest(descriptor.Digest))
|
|
||||||
|
for tag, descriptor := range repos[0].Tags {
|
||||||
|
imageManifestData, err := metaDB.GetFullImageMeta(ctx, repo, tag)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(manifestMeta.ManifestBlob, ShouldNotBeNil)
|
|
||||||
So(manifestMeta.ConfigBlob, ShouldNotBeNil)
|
|
||||||
|
|
||||||
if descriptor.Digest == signedManifestDigest.String() {
|
if descriptor.Digest == signedManifestDigest.String() {
|
||||||
So(manifestMeta.Signatures, ShouldNotBeEmpty)
|
So(imageManifestData.Signatures, ShouldNotBeEmpty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -555,10 +307,8 @@ func RunParseStorageTests(rootDir string, metaDB mTypes.MetaDB) {
|
|||||||
err = meta.ParseStorage(metaDB, storeController, log.NewLogger("debug", ""))
|
err = meta.ParseStorage(metaDB, storeController, log.NewLogger("debug", ""))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
repos, err := metaDB.GetMultipleRepoMeta(
|
repos, err := metaDB.GetMultipleRepoMeta(context.Background(),
|
||||||
context.Background(),
|
func(repoMeta mTypes.RepoMeta) bool { return true })
|
||||||
func(repoMeta mTypes.RepoMetadata) bool { return true },
|
|
||||||
)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
for _, desc := range repos[0].Tags {
|
for _, desc := range repos[0].Tags {
|
||||||
@ -577,15 +327,12 @@ func RunParseStorageTests(rootDir string, metaDB mTypes.MetaDB) {
|
|||||||
|
|
||||||
storeController := storage.StoreController{DefaultStore: imageStore}
|
storeController := storage.StoreController{DefaultStore: imageStore}
|
||||||
// add an image
|
// add an image
|
||||||
image, err := deprecated.GetRandomImage() //nolint:staticcheck
|
image := CreateRandomImage() //nolint:staticcheck
|
||||||
|
|
||||||
|
err := WriteImageToFileSystem(image, repo, "tag", storeController)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
manifestDigest := image.Digest()
|
err = metaDB.SetRepoReference(repo, "tag", image.AsImageMeta())
|
||||||
|
|
||||||
err = WriteImageToFileSystem(image, repo, "tag", storeController)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
err = metaDB.SetRepoReference(repo, "tag", manifestDigest, ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
err = metaDB.IncrementRepoStars(repo)
|
err = metaDB.IncrementRepoStars(repo)
|
||||||
@ -597,30 +344,20 @@ func RunParseStorageTests(rootDir string, metaDB mTypes.MetaDB) {
|
|||||||
err = metaDB.IncrementImageDownloads(repo, "tag")
|
err = metaDB.IncrementImageDownloads(repo, "tag")
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
repoMeta, err := metaDB.GetRepoMeta(repo)
|
repoMeta, err := metaDB.GetRepoMeta(context.Background(), repo)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
So(repoMeta.Statistics[manifestDigest.String()].DownloadCount, ShouldEqual, 3)
|
So(repoMeta.Statistics[image.DigestStr()].DownloadCount, ShouldEqual, 3)
|
||||||
So(repoMeta.Stars, ShouldEqual, 1)
|
So(repoMeta.StarCount, ShouldEqual, 1)
|
||||||
|
|
||||||
err = meta.ParseStorage(metaDB, storeController, log.NewLogger("debug", ""))
|
err = meta.ParseStorage(metaDB, storeController, log.NewLogger("debug", ""))
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
repoMeta, err = metaDB.GetRepoMeta(repo)
|
repoMeta, err = metaDB.GetRepoMeta(context.Background(), repo)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
So(repoMeta.Statistics[manifestDigest.String()].DownloadCount, ShouldEqual, 3)
|
So(repoMeta.Statistics[image.DigestStr()].DownloadCount, ShouldEqual, 3)
|
||||||
So(repoMeta.Stars, ShouldEqual, 1)
|
So(repoMeta.StarCount, ShouldEqual, 1)
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetReferredInfo(t *testing.T) {
|
|
||||||
Convey("GetReferredInfo error", t, func() {
|
|
||||||
_, _, _, err := meta.GetReferredInfo([]byte("bad json"), "digest", ispec.MediaTypeImageManifest)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
|
|
||||||
_, _, _, err = meta.GetReferredInfo([]byte("bad json"), "digest", ispec.MediaTypeImageIndex)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
628
pkg/meta/proto/gen/config.pb.go
Normal file
628
pkg/meta/proto/gen/config.pb.go
Normal file
@ -0,0 +1,628 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.31.0
|
||||||
|
// protoc v4.24.4
|
||||||
|
// source: oci/config.proto
|
||||||
|
|
||||||
|
package gen
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Image struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Created *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=Created,proto3,oneof" json:"Created,omitempty"`
|
||||||
|
Author *string `protobuf:"bytes,2,opt,name=Author,proto3,oneof" json:"Author,omitempty"`
|
||||||
|
Platform *Platform `protobuf:"bytes,3,opt,name=Platform,proto3" json:"Platform,omitempty"`
|
||||||
|
Config *ImageConfig `protobuf:"bytes,4,opt,name=Config,proto3,oneof" json:"Config,omitempty"`
|
||||||
|
RootFS *RootFS `protobuf:"bytes,5,opt,name=RootFS,proto3,oneof" json:"RootFS,omitempty"`
|
||||||
|
History []*History `protobuf:"bytes,6,rep,name=History,proto3" json:"History,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Image) Reset() {
|
||||||
|
*x = Image{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_oci_config_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Image) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Image) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Image) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_oci_config_proto_msgTypes[0]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Image.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Image) Descriptor() ([]byte, []int) {
|
||||||
|
return file_oci_config_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Image) GetCreated() *timestamppb.Timestamp {
|
||||||
|
if x != nil {
|
||||||
|
return x.Created
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Image) GetAuthor() string {
|
||||||
|
if x != nil && x.Author != nil {
|
||||||
|
return *x.Author
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Image) GetPlatform() *Platform {
|
||||||
|
if x != nil {
|
||||||
|
return x.Platform
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Image) GetConfig() *ImageConfig {
|
||||||
|
if x != nil {
|
||||||
|
return x.Config
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Image) GetRootFS() *RootFS {
|
||||||
|
if x != nil {
|
||||||
|
return x.RootFS
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Image) GetHistory() []*History {
|
||||||
|
if x != nil {
|
||||||
|
return x.History
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImageConfig struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
ExposedPorts map[string]*EmptyMessage `protobuf:"bytes,1,rep,name=ExposedPorts,proto3" json:"ExposedPorts,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||||
|
Volumes map[string]*EmptyMessage `protobuf:"bytes,2,rep,name=Volumes,proto3" json:"Volumes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||||
|
Labels map[string]string `protobuf:"bytes,3,rep,name=Labels,proto3" json:"Labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||||
|
User string `protobuf:"bytes,4,opt,name=User,proto3" json:"User,omitempty"`
|
||||||
|
Env []string `protobuf:"bytes,5,rep,name=Env,proto3" json:"Env,omitempty"`
|
||||||
|
Entrypoint []string `protobuf:"bytes,6,rep,name=Entrypoint,proto3" json:"Entrypoint,omitempty"`
|
||||||
|
Cmd []string `protobuf:"bytes,7,rep,name=Cmd,proto3" json:"Cmd,omitempty"`
|
||||||
|
WorkingDir *string `protobuf:"bytes,8,opt,name=WorkingDir,proto3,oneof" json:"WorkingDir,omitempty"`
|
||||||
|
StopSignal *string `protobuf:"bytes,9,opt,name=StopSignal,proto3,oneof" json:"StopSignal,omitempty"`
|
||||||
|
ArgsEscaped bool `protobuf:"varint,10,opt,name=ArgsEscaped,proto3" json:"ArgsEscaped,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ImageConfig) Reset() {
|
||||||
|
*x = ImageConfig{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_oci_config_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ImageConfig) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ImageConfig) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ImageConfig) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_oci_config_proto_msgTypes[1]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ImageConfig.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ImageConfig) Descriptor() ([]byte, []int) {
|
||||||
|
return file_oci_config_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ImageConfig) GetExposedPorts() map[string]*EmptyMessage {
|
||||||
|
if x != nil {
|
||||||
|
return x.ExposedPorts
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ImageConfig) GetVolumes() map[string]*EmptyMessage {
|
||||||
|
if x != nil {
|
||||||
|
return x.Volumes
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ImageConfig) GetLabels() map[string]string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Labels
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ImageConfig) GetUser() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.User
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ImageConfig) GetEnv() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Env
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ImageConfig) GetEntrypoint() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Entrypoint
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ImageConfig) GetCmd() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Cmd
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ImageConfig) GetWorkingDir() string {
|
||||||
|
if x != nil && x.WorkingDir != nil {
|
||||||
|
return *x.WorkingDir
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ImageConfig) GetStopSignal() string {
|
||||||
|
if x != nil && x.StopSignal != nil {
|
||||||
|
return *x.StopSignal
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ImageConfig) GetArgsEscaped() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.ArgsEscaped
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type RootFS struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Type string `protobuf:"bytes,1,opt,name=Type,proto3" json:"Type,omitempty"`
|
||||||
|
DiffIDs []string `protobuf:"bytes,2,rep,name=DiffIDs,proto3" json:"DiffIDs,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RootFS) Reset() {
|
||||||
|
*x = RootFS{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_oci_config_proto_msgTypes[2]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RootFS) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*RootFS) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *RootFS) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_oci_config_proto_msgTypes[2]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use RootFS.ProtoReflect.Descriptor instead.
|
||||||
|
func (*RootFS) Descriptor() ([]byte, []int) {
|
||||||
|
return file_oci_config_proto_rawDescGZIP(), []int{2}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RootFS) GetType() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Type
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RootFS) GetDiffIDs() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.DiffIDs
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type History struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Created *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=Created,proto3,oneof" json:"Created,omitempty"`
|
||||||
|
CreatedBy *string `protobuf:"bytes,2,opt,name=CreatedBy,proto3,oneof" json:"CreatedBy,omitempty"`
|
||||||
|
Author *string `protobuf:"bytes,3,opt,name=Author,proto3,oneof" json:"Author,omitempty"`
|
||||||
|
Comment *string `protobuf:"bytes,4,opt,name=Comment,proto3,oneof" json:"Comment,omitempty"`
|
||||||
|
EmptyLayer *bool `protobuf:"varint,5,opt,name=EmptyLayer,proto3,oneof" json:"EmptyLayer,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *History) Reset() {
|
||||||
|
*x = History{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_oci_config_proto_msgTypes[3]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *History) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*History) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *History) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_oci_config_proto_msgTypes[3]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use History.ProtoReflect.Descriptor instead.
|
||||||
|
func (*History) Descriptor() ([]byte, []int) {
|
||||||
|
return file_oci_config_proto_rawDescGZIP(), []int{3}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *History) GetCreated() *timestamppb.Timestamp {
|
||||||
|
if x != nil {
|
||||||
|
return x.Created
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *History) GetCreatedBy() string {
|
||||||
|
if x != nil && x.CreatedBy != nil {
|
||||||
|
return *x.CreatedBy
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *History) GetAuthor() string {
|
||||||
|
if x != nil && x.Author != nil {
|
||||||
|
return *x.Author
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *History) GetComment() string {
|
||||||
|
if x != nil && x.Comment != nil {
|
||||||
|
return *x.Comment
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *History) GetEmptyLayer() bool {
|
||||||
|
if x != nil && x.EmptyLayer != nil {
|
||||||
|
return *x.EmptyLayer
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type EmptyMessage struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EmptyMessage) Reset() {
|
||||||
|
*x = EmptyMessage{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_oci_config_proto_msgTypes[4]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EmptyMessage) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*EmptyMessage) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *EmptyMessage) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_oci_config_proto_msgTypes[4]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use EmptyMessage.ProtoReflect.Descriptor instead.
|
||||||
|
func (*EmptyMessage) Descriptor() ([]byte, []int) {
|
||||||
|
return file_oci_config_proto_rawDescGZIP(), []int{4}
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_oci_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_oci_config_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x10, 0x6f, 0x63, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f,
|
||||||
|
0x74, 0x6f, 0x12, 0x06, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x1a, 0x13, 0x6f, 0x63, 0x69, 0x2f,
|
||||||
|
0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
|
||||||
|
0x14, 0x6f, 0x63, 0x69, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e,
|
||||||
|
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc4, 0x02, 0x0a, 0x05, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12,
|
||||||
|
0x39, 0x0a, 0x07, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
||||||
|
0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
|
||||||
|
0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x48, 0x00, 0x52, 0x07,
|
||||||
|
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x41, 0x75,
|
||||||
|
0x74, 0x68, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x06, 0x41, 0x75,
|
||||||
|
0x74, 0x68, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x2c, 0x0a, 0x08, 0x50, 0x6c, 0x61, 0x74, 0x66,
|
||||||
|
0x6f, 0x72, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6f, 0x63, 0x69, 0x5f,
|
||||||
|
0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x50, 0x6c, 0x61,
|
||||||
|
0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x30, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18,
|
||||||
|
0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x2e, 0x49,
|
||||||
|
0x6d, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x02, 0x52, 0x06, 0x43, 0x6f,
|
||||||
|
0x6e, 0x66, 0x69, 0x67, 0x88, 0x01, 0x01, 0x12, 0x2b, 0x0a, 0x06, 0x52, 0x6f, 0x6f, 0x74, 0x46,
|
||||||
|
0x53, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31,
|
||||||
|
0x2e, 0x52, 0x6f, 0x6f, 0x74, 0x46, 0x53, 0x48, 0x03, 0x52, 0x06, 0x52, 0x6f, 0x6f, 0x74, 0x46,
|
||||||
|
0x53, 0x88, 0x01, 0x01, 0x12, 0x29, 0x0a, 0x07, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x18,
|
||||||
|
0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x2e, 0x48,
|
||||||
|
0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x07, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x42,
|
||||||
|
0x0a, 0x0a, 0x08, 0x5f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x09, 0x0a, 0x07, 0x5f,
|
||||||
|
0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||||
|
0x67, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x46, 0x53, 0x22, 0x93, 0x05, 0x0a,
|
||||||
|
0x0b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x49, 0x0a, 0x0c,
|
||||||
|
0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03,
|
||||||
|
0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x2e, 0x49, 0x6d, 0x61, 0x67,
|
||||||
|
0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x50,
|
||||||
|
0x6f, 0x72, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x45, 0x78, 0x70, 0x6f, 0x73,
|
||||||
|
0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x07, 0x56, 0x6f, 0x6c, 0x75, 0x6d,
|
||||||
|
0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6f, 0x63, 0x69, 0x5f, 0x76,
|
||||||
|
0x31, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x56, 0x6f,
|
||||||
|
0x6c, 0x75, 0x6d, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x56, 0x6f, 0x6c, 0x75,
|
||||||
|
0x6d, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x03, 0x20,
|
||||||
|
0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x2e, 0x49, 0x6d, 0x61,
|
||||||
|
0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45,
|
||||||
|
0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x12, 0x0a, 0x04,
|
||||||
|
0x55, 0x73, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x55, 0x73, 0x65, 0x72,
|
||||||
|
0x12, 0x10, 0x0a, 0x03, 0x45, 0x6e, 0x76, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x45,
|
||||||
|
0x6e, 0x76, 0x12, 0x1e, 0x0a, 0x0a, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||||
|
0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69,
|
||||||
|
0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x43, 0x6d, 0x64, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||||
|
0x03, 0x43, 0x6d, 0x64, 0x12, 0x23, 0x0a, 0x0a, 0x57, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x44,
|
||||||
|
0x69, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x57, 0x6f, 0x72, 0x6b,
|
||||||
|
0x69, 0x6e, 0x67, 0x44, 0x69, 0x72, 0x88, 0x01, 0x01, 0x12, 0x23, 0x0a, 0x0a, 0x53, 0x74, 0x6f,
|
||||||
|
0x70, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52,
|
||||||
|
0x0a, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x20,
|
||||||
|
0x0a, 0x0b, 0x41, 0x72, 0x67, 0x73, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x64, 0x18, 0x0a, 0x20,
|
||||||
|
0x01, 0x28, 0x08, 0x52, 0x0b, 0x41, 0x72, 0x67, 0x73, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x64,
|
||||||
|
0x1a, 0x55, 0x0a, 0x11, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x73,
|
||||||
|
0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
|
||||||
|
0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||||
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x2e,
|
||||||
|
0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x76, 0x61,
|
||||||
|
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x50, 0x0a, 0x0c, 0x56, 0x6f, 0x6c, 0x75, 0x6d,
|
||||||
|
0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
|
||||||
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c,
|
||||||
|
0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6f, 0x63, 0x69, 0x5f, 0x76,
|
||||||
|
0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05,
|
||||||
|
0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62,
|
||||||
|
0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
|
||||||
|
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
|
||||||
|
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||||
|
0x3a, 0x02, 0x38, 0x01, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x57, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67,
|
||||||
|
0x44, 0x69, 0x72, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x69, 0x67, 0x6e,
|
||||||
|
0x61, 0x6c, 0x22, 0x36, 0x0a, 0x06, 0x52, 0x6f, 0x6f, 0x74, 0x46, 0x53, 0x12, 0x12, 0x0a, 0x04,
|
||||||
|
0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65,
|
||||||
|
0x12, 0x18, 0x0a, 0x07, 0x44, 0x69, 0x66, 0x66, 0x49, 0x44, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
|
||||||
|
0x09, 0x52, 0x07, 0x44, 0x69, 0x66, 0x66, 0x49, 0x44, 0x73, 0x22, 0x88, 0x02, 0x0a, 0x07, 0x48,
|
||||||
|
0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x39, 0x0a, 0x07, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
|
||||||
|
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||||
|
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
|
||||||
|
0x61, 0x6d, 0x70, 0x48, 0x00, 0x52, 0x07, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x88, 0x01,
|
||||||
|
0x01, 0x12, 0x21, 0x0a, 0x09, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x18, 0x02,
|
||||||
|
0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x09, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42,
|
||||||
|
0x79, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, 0x03,
|
||||||
|
0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x06, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x88, 0x01,
|
||||||
|
0x01, 0x12, 0x1d, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01,
|
||||||
|
0x28, 0x09, 0x48, 0x03, 0x52, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x88, 0x01, 0x01,
|
||||||
|
0x12, 0x23, 0x0a, 0x0a, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x05,
|
||||||
|
0x20, 0x01, 0x28, 0x08, 0x48, 0x04, 0x52, 0x0a, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4c, 0x61, 0x79,
|
||||||
|
0x65, 0x72, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
|
||||||
|
0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x42,
|
||||||
|
0x09, 0x0a, 0x07, 0x5f, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x43,
|
||||||
|
0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x45, 0x6d, 0x70, 0x74, 0x79,
|
||||||
|
0x4c, 0x61, 0x79, 0x65, 0x72, 0x22, 0x0e, 0x0a, 0x0c, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65,
|
||||||
|
0x73, 0x73, 0x61, 0x67, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_oci_config_proto_rawDescOnce sync.Once
|
||||||
|
file_oci_config_proto_rawDescData = file_oci_config_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_oci_config_proto_rawDescGZIP() []byte {
|
||||||
|
file_oci_config_proto_rawDescOnce.Do(func() {
|
||||||
|
file_oci_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_oci_config_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_oci_config_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_oci_config_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
|
||||||
|
var file_oci_config_proto_goTypes = []interface{}{
|
||||||
|
(*Image)(nil), // 0: oci_v1.Image
|
||||||
|
(*ImageConfig)(nil), // 1: oci_v1.ImageConfig
|
||||||
|
(*RootFS)(nil), // 2: oci_v1.RootFS
|
||||||
|
(*History)(nil), // 3: oci_v1.History
|
||||||
|
(*EmptyMessage)(nil), // 4: oci_v1.EmptyMessage
|
||||||
|
nil, // 5: oci_v1.ImageConfig.ExposedPortsEntry
|
||||||
|
nil, // 6: oci_v1.ImageConfig.VolumesEntry
|
||||||
|
nil, // 7: oci_v1.ImageConfig.LabelsEntry
|
||||||
|
(*timestamppb.Timestamp)(nil), // 8: google.protobuf.Timestamp
|
||||||
|
(*Platform)(nil), // 9: oci_v1.Platform
|
||||||
|
}
|
||||||
|
var file_oci_config_proto_depIdxs = []int32{
|
||||||
|
8, // 0: oci_v1.Image.Created:type_name -> google.protobuf.Timestamp
|
||||||
|
9, // 1: oci_v1.Image.Platform:type_name -> oci_v1.Platform
|
||||||
|
1, // 2: oci_v1.Image.Config:type_name -> oci_v1.ImageConfig
|
||||||
|
2, // 3: oci_v1.Image.RootFS:type_name -> oci_v1.RootFS
|
||||||
|
3, // 4: oci_v1.Image.History:type_name -> oci_v1.History
|
||||||
|
5, // 5: oci_v1.ImageConfig.ExposedPorts:type_name -> oci_v1.ImageConfig.ExposedPortsEntry
|
||||||
|
6, // 6: oci_v1.ImageConfig.Volumes:type_name -> oci_v1.ImageConfig.VolumesEntry
|
||||||
|
7, // 7: oci_v1.ImageConfig.Labels:type_name -> oci_v1.ImageConfig.LabelsEntry
|
||||||
|
8, // 8: oci_v1.History.Created:type_name -> google.protobuf.Timestamp
|
||||||
|
4, // 9: oci_v1.ImageConfig.ExposedPortsEntry.value:type_name -> oci_v1.EmptyMessage
|
||||||
|
4, // 10: oci_v1.ImageConfig.VolumesEntry.value:type_name -> oci_v1.EmptyMessage
|
||||||
|
11, // [11:11] is the sub-list for method output_type
|
||||||
|
11, // [11:11] is the sub-list for method input_type
|
||||||
|
11, // [11:11] is the sub-list for extension type_name
|
||||||
|
11, // [11:11] is the sub-list for extension extendee
|
||||||
|
0, // [0:11] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_oci_config_proto_init() }
|
||||||
|
func file_oci_config_proto_init() {
|
||||||
|
if File_oci_config_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
file_oci_descriptor_proto_init()
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_oci_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*Image); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_oci_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ImageConfig); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_oci_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*RootFS); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_oci_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*History); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_oci_config_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*EmptyMessage); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_oci_config_proto_msgTypes[0].OneofWrappers = []interface{}{}
|
||||||
|
file_oci_config_proto_msgTypes[1].OneofWrappers = []interface{}{}
|
||||||
|
file_oci_config_proto_msgTypes[3].OneofWrappers = []interface{}{}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_oci_config_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 8,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_oci_config_proto_goTypes,
|
||||||
|
DependencyIndexes: file_oci_config_proto_depIdxs,
|
||||||
|
MessageInfos: file_oci_config_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_oci_config_proto = out.File
|
||||||
|
file_oci_config_proto_rawDesc = nil
|
||||||
|
file_oci_config_proto_goTypes = nil
|
||||||
|
file_oci_config_proto_depIdxs = nil
|
||||||
|
}
|
328
pkg/meta/proto/gen/descriptor.pb.go
Normal file
328
pkg/meta/proto/gen/descriptor.pb.go
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.31.0
|
||||||
|
// protoc v4.24.4
|
||||||
|
// source: oci/descriptor.proto
|
||||||
|
|
||||||
|
package gen
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Descriptor struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
MediaType string `protobuf:"bytes,1,opt,name=MediaType,proto3" json:"MediaType,omitempty"`
|
||||||
|
Digest string `protobuf:"bytes,2,opt,name=Digest,proto3" json:"Digest,omitempty"`
|
||||||
|
Size int64 `protobuf:"varint,3,opt,name=Size,proto3" json:"Size,omitempty"`
|
||||||
|
URLs []string `protobuf:"bytes,4,rep,name=URLs,proto3" json:"URLs,omitempty"`
|
||||||
|
Data []byte `protobuf:"bytes,5,opt,name=Data,proto3" json:"Data,omitempty"`
|
||||||
|
Platform *Platform `protobuf:"bytes,6,opt,name=Platform,proto3,oneof" json:"Platform,omitempty"`
|
||||||
|
ArtifactType *string `protobuf:"bytes,7,opt,name=ArtifactType,proto3,oneof" json:"ArtifactType,omitempty"`
|
||||||
|
Annotations map[string]string `protobuf:"bytes,8,rep,name=Annotations,proto3" json:"Annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Descriptor) Reset() {
|
||||||
|
*x = Descriptor{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_oci_descriptor_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Descriptor) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Descriptor) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Descriptor) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_oci_descriptor_proto_msgTypes[0]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Descriptor.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Descriptor) Descriptor() ([]byte, []int) {
|
||||||
|
return file_oci_descriptor_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Descriptor) GetMediaType() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.MediaType
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Descriptor) GetDigest() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Digest
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Descriptor) GetSize() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Size
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Descriptor) GetURLs() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.URLs
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Descriptor) GetData() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.Data
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Descriptor) GetPlatform() *Platform {
|
||||||
|
if x != nil {
|
||||||
|
return x.Platform
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Descriptor) GetArtifactType() string {
|
||||||
|
if x != nil && x.ArtifactType != nil {
|
||||||
|
return *x.ArtifactType
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Descriptor) GetAnnotations() map[string]string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Annotations
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Platform struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Architecture string `protobuf:"bytes,1,opt,name=Architecture,proto3" json:"Architecture,omitempty"`
|
||||||
|
OS string `protobuf:"bytes,2,opt,name=OS,proto3" json:"OS,omitempty"`
|
||||||
|
OSVersion *string `protobuf:"bytes,3,opt,name=OSVersion,proto3,oneof" json:"OSVersion,omitempty"`
|
||||||
|
OSFeatures []string `protobuf:"bytes,4,rep,name=OSFeatures,proto3" json:"OSFeatures,omitempty"`
|
||||||
|
Variant *string `protobuf:"bytes,5,opt,name=Variant,proto3,oneof" json:"Variant,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Platform) Reset() {
|
||||||
|
*x = Platform{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_oci_descriptor_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Platform) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Platform) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Platform) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_oci_descriptor_proto_msgTypes[1]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Platform.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Platform) Descriptor() ([]byte, []int) {
|
||||||
|
return file_oci_descriptor_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Platform) GetArchitecture() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Architecture
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Platform) GetOS() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.OS
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Platform) GetOSVersion() string {
|
||||||
|
if x != nil && x.OSVersion != nil {
|
||||||
|
return *x.OSVersion
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Platform) GetOSFeatures() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.OSFeatures
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Platform) GetVariant() string {
|
||||||
|
if x != nil && x.Variant != nil {
|
||||||
|
return *x.Variant
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_oci_descriptor_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_oci_descriptor_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x14, 0x6f, 0x63, 0x69, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
|
||||||
|
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x22, 0xff,
|
||||||
|
0x02, 0x0a, 0x0a, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x1c, 0x0a,
|
||||||
|
0x09, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||||
|
0x52, 0x09, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x44,
|
||||||
|
0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x44, 0x69, 0x67,
|
||||||
|
0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||||
|
0x03, 0x52, 0x04, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x55, 0x52, 0x4c, 0x73, 0x18,
|
||||||
|
0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x55, 0x52, 0x4c, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x44,
|
||||||
|
0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x44, 0x61, 0x74, 0x61, 0x12,
|
||||||
|
0x31, 0x0a, 0x08, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x06, 0x20, 0x01, 0x28,
|
||||||
|
0x0b, 0x32, 0x10, 0x2e, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66,
|
||||||
|
0x6f, 0x72, 0x6d, 0x48, 0x00, 0x52, 0x08, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x88,
|
||||||
|
0x01, 0x01, 0x12, 0x27, 0x0a, 0x0c, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x54, 0x79,
|
||||||
|
0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0c, 0x41, 0x72, 0x74, 0x69,
|
||||||
|
0x66, 0x61, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x88, 0x01, 0x01, 0x12, 0x45, 0x0a, 0x0b, 0x41,
|
||||||
|
0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b,
|
||||||
|
0x32, 0x23, 0x2e, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
|
||||||
|
0x70, 0x74, 0x6f, 0x72, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
|
||||||
|
0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f,
|
||||||
|
0x6e, 0x73, 0x1a, 0x3e, 0x0a, 0x10, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
|
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
|
||||||
|
0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
|
||||||
|
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
|
||||||
|
0x38, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x42,
|
||||||
|
0x0f, 0x0a, 0x0d, 0x5f, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65,
|
||||||
|
0x22, 0xba, 0x01, 0x0a, 0x08, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x22, 0x0a,
|
||||||
|
0x0c, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20,
|
||||||
|
0x01, 0x28, 0x09, 0x52, 0x0c, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72,
|
||||||
|
0x65, 0x12, 0x0e, 0x0a, 0x02, 0x4f, 0x53, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x4f,
|
||||||
|
0x53, 0x12, 0x21, 0x0a, 0x09, 0x4f, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03,
|
||||||
|
0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x4f, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
|
||||||
|
0x6e, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x0a, 0x4f, 0x53, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72,
|
||||||
|
0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x4f, 0x53, 0x46, 0x65, 0x61, 0x74,
|
||||||
|
0x75, 0x72, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x07, 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x18,
|
||||||
|
0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74,
|
||||||
|
0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x4f, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
|
||||||
|
0x6e, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x62, 0x06, 0x70,
|
||||||
|
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_oci_descriptor_proto_rawDescOnce sync.Once
|
||||||
|
file_oci_descriptor_proto_rawDescData = file_oci_descriptor_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_oci_descriptor_proto_rawDescGZIP() []byte {
|
||||||
|
file_oci_descriptor_proto_rawDescOnce.Do(func() {
|
||||||
|
file_oci_descriptor_proto_rawDescData = protoimpl.X.CompressGZIP(file_oci_descriptor_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_oci_descriptor_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_oci_descriptor_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
|
||||||
|
var file_oci_descriptor_proto_goTypes = []interface{}{
|
||||||
|
(*Descriptor)(nil), // 0: oci_v1.Descriptor
|
||||||
|
(*Platform)(nil), // 1: oci_v1.Platform
|
||||||
|
nil, // 2: oci_v1.Descriptor.AnnotationsEntry
|
||||||
|
}
|
||||||
|
var file_oci_descriptor_proto_depIdxs = []int32{
|
||||||
|
1, // 0: oci_v1.Descriptor.Platform:type_name -> oci_v1.Platform
|
||||||
|
2, // 1: oci_v1.Descriptor.Annotations:type_name -> oci_v1.Descriptor.AnnotationsEntry
|
||||||
|
2, // [2:2] is the sub-list for method output_type
|
||||||
|
2, // [2:2] is the sub-list for method input_type
|
||||||
|
2, // [2:2] is the sub-list for extension type_name
|
||||||
|
2, // [2:2] is the sub-list for extension extendee
|
||||||
|
0, // [0:2] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_oci_descriptor_proto_init() }
|
||||||
|
func file_oci_descriptor_proto_init() {
|
||||||
|
if File_oci_descriptor_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_oci_descriptor_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*Descriptor); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_oci_descriptor_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*Platform); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_oci_descriptor_proto_msgTypes[0].OneofWrappers = []interface{}{}
|
||||||
|
file_oci_descriptor_proto_msgTypes[1].OneofWrappers = []interface{}{}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_oci_descriptor_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 3,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_oci_descriptor_proto_goTypes,
|
||||||
|
DependencyIndexes: file_oci_descriptor_proto_depIdxs,
|
||||||
|
MessageInfos: file_oci_descriptor_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_oci_descriptor_proto = out.File
|
||||||
|
file_oci_descriptor_proto_rawDesc = nil
|
||||||
|
file_oci_descriptor_proto_goTypes = nil
|
||||||
|
file_oci_descriptor_proto_depIdxs = nil
|
||||||
|
}
|
217
pkg/meta/proto/gen/index.pb.go
Normal file
217
pkg/meta/proto/gen/index.pb.go
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.31.0
|
||||||
|
// protoc v4.24.4
|
||||||
|
// source: oci/index.proto
|
||||||
|
|
||||||
|
package gen
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Index struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Versioned *Versioned `protobuf:"bytes,1,opt,name=Versioned,proto3" json:"Versioned,omitempty"`
|
||||||
|
MediaType *string `protobuf:"bytes,2,opt,name=MediaType,proto3,oneof" json:"MediaType,omitempty"`
|
||||||
|
ArtifactType *string `protobuf:"bytes,3,opt,name=ArtifactType,proto3,oneof" json:"ArtifactType,omitempty"`
|
||||||
|
Manifests []*Descriptor `protobuf:"bytes,4,rep,name=Manifests,proto3" json:"Manifests,omitempty"`
|
||||||
|
Subject *Descriptor `protobuf:"bytes,5,opt,name=Subject,proto3,oneof" json:"Subject,omitempty"`
|
||||||
|
Annotations map[string]string `protobuf:"bytes,6,rep,name=Annotations,proto3" json:"Annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Index) Reset() {
|
||||||
|
*x = Index{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_oci_index_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Index) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Index) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Index) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_oci_index_proto_msgTypes[0]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Index.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Index) Descriptor() ([]byte, []int) {
|
||||||
|
return file_oci_index_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Index) GetVersioned() *Versioned {
|
||||||
|
if x != nil {
|
||||||
|
return x.Versioned
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Index) GetMediaType() string {
|
||||||
|
if x != nil && x.MediaType != nil {
|
||||||
|
return *x.MediaType
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Index) GetArtifactType() string {
|
||||||
|
if x != nil && x.ArtifactType != nil {
|
||||||
|
return *x.ArtifactType
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Index) GetManifests() []*Descriptor {
|
||||||
|
if x != nil {
|
||||||
|
return x.Manifests
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Index) GetSubject() *Descriptor {
|
||||||
|
if x != nil {
|
||||||
|
return x.Subject
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Index) GetAnnotations() map[string]string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Annotations
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_oci_index_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_oci_index_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x0f, 0x6f, 0x63, 0x69, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||||
|
0x6f, 0x12, 0x06, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x1a, 0x14, 0x6f, 0x63, 0x69, 0x2f, 0x64,
|
||||||
|
0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
|
||||||
|
0x13, 0x6f, 0x63, 0x69, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x2e, 0x70,
|
||||||
|
0x72, 0x6f, 0x74, 0x6f, 0x22, 0x96, 0x03, 0x0a, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2f,
|
||||||
|
0x0a, 0x09, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
|
0x0b, 0x32, 0x11, 0x2e, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69,
|
||||||
|
0x6f, 0x6e, 0x65, 0x64, 0x52, 0x09, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x12,
|
||||||
|
0x21, 0x0a, 0x09, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01,
|
||||||
|
0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x54, 0x79, 0x70, 0x65, 0x88,
|
||||||
|
0x01, 0x01, 0x12, 0x27, 0x0a, 0x0c, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x54, 0x79,
|
||||||
|
0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0c, 0x41, 0x72, 0x74, 0x69,
|
||||||
|
0x66, 0x61, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x88, 0x01, 0x01, 0x12, 0x30, 0x0a, 0x09, 0x4d,
|
||||||
|
0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12,
|
||||||
|
0x2e, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
|
||||||
|
0x6f, 0x72, 0x52, 0x09, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x73, 0x12, 0x31, 0x0a,
|
||||||
|
0x07, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12,
|
||||||
|
0x2e, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
|
||||||
|
0x6f, 0x72, 0x48, 0x02, 0x52, 0x07, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x88, 0x01, 0x01,
|
||||||
|
0x12, 0x40, 0x0a, 0x0b, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
|
||||||
|
0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x2e, 0x49,
|
||||||
|
0x6e, 0x64, 0x65, 0x78, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
|
||||||
|
0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f,
|
||||||
|
0x6e, 0x73, 0x1a, 0x3e, 0x0a, 0x10, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
|
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
|
||||||
|
0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
|
||||||
|
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
|
||||||
|
0x38, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x54, 0x79, 0x70, 0x65,
|
||||||
|
0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x54, 0x79, 0x70,
|
||||||
|
0x65, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x62, 0x06, 0x70,
|
||||||
|
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_oci_index_proto_rawDescOnce sync.Once
|
||||||
|
file_oci_index_proto_rawDescData = file_oci_index_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_oci_index_proto_rawDescGZIP() []byte {
|
||||||
|
file_oci_index_proto_rawDescOnce.Do(func() {
|
||||||
|
file_oci_index_proto_rawDescData = protoimpl.X.CompressGZIP(file_oci_index_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_oci_index_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_oci_index_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||||
|
var file_oci_index_proto_goTypes = []interface{}{
|
||||||
|
(*Index)(nil), // 0: oci_v1.Index
|
||||||
|
nil, // 1: oci_v1.Index.AnnotationsEntry
|
||||||
|
(*Versioned)(nil), // 2: oci_v1.Versioned
|
||||||
|
(*Descriptor)(nil), // 3: oci_v1.Descriptor
|
||||||
|
}
|
||||||
|
var file_oci_index_proto_depIdxs = []int32{
|
||||||
|
2, // 0: oci_v1.Index.Versioned:type_name -> oci_v1.Versioned
|
||||||
|
3, // 1: oci_v1.Index.Manifests:type_name -> oci_v1.Descriptor
|
||||||
|
3, // 2: oci_v1.Index.Subject:type_name -> oci_v1.Descriptor
|
||||||
|
1, // 3: oci_v1.Index.Annotations:type_name -> oci_v1.Index.AnnotationsEntry
|
||||||
|
4, // [4:4] is the sub-list for method output_type
|
||||||
|
4, // [4:4] is the sub-list for method input_type
|
||||||
|
4, // [4:4] is the sub-list for extension type_name
|
||||||
|
4, // [4:4] is the sub-list for extension extendee
|
||||||
|
0, // [0:4] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_oci_index_proto_init() }
|
||||||
|
func file_oci_index_proto_init() {
|
||||||
|
if File_oci_index_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
file_oci_descriptor_proto_init()
|
||||||
|
file_oci_versioned_proto_init()
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_oci_index_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*Index); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_oci_index_proto_msgTypes[0].OneofWrappers = []interface{}{}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_oci_index_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 2,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_oci_index_proto_goTypes,
|
||||||
|
DependencyIndexes: file_oci_index_proto_depIdxs,
|
||||||
|
MessageInfos: file_oci_index_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_oci_index_proto = out.File
|
||||||
|
file_oci_index_proto_rawDesc = nil
|
||||||
|
file_oci_index_proto_goTypes = nil
|
||||||
|
file_oci_index_proto_depIdxs = nil
|
||||||
|
}
|
229
pkg/meta/proto/gen/manifest.pb.go
Normal file
229
pkg/meta/proto/gen/manifest.pb.go
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.31.0
|
||||||
|
// protoc v4.24.4
|
||||||
|
// source: oci/manifest.proto
|
||||||
|
|
||||||
|
package gen
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Manifest struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Versioned *Versioned `protobuf:"bytes,1,opt,name=Versioned,proto3" json:"Versioned,omitempty"`
|
||||||
|
MediaType *string `protobuf:"bytes,2,opt,name=MediaType,proto3,oneof" json:"MediaType,omitempty"`
|
||||||
|
ArtifactType *string `protobuf:"bytes,3,opt,name=ArtifactType,proto3,oneof" json:"ArtifactType,omitempty"`
|
||||||
|
Config *Descriptor `protobuf:"bytes,4,opt,name=Config,proto3" json:"Config,omitempty"`
|
||||||
|
Layers []*Descriptor `protobuf:"bytes,5,rep,name=Layers,proto3" json:"Layers,omitempty"`
|
||||||
|
Subject *Descriptor `protobuf:"bytes,6,opt,name=Subject,proto3,oneof" json:"Subject,omitempty"`
|
||||||
|
Annotations map[string]string `protobuf:"bytes,7,rep,name=Annotations,proto3" json:"Annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Manifest) Reset() {
|
||||||
|
*x = Manifest{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_oci_manifest_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Manifest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Manifest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Manifest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_oci_manifest_proto_msgTypes[0]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Manifest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Manifest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_oci_manifest_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Manifest) GetVersioned() *Versioned {
|
||||||
|
if x != nil {
|
||||||
|
return x.Versioned
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Manifest) GetMediaType() string {
|
||||||
|
if x != nil && x.MediaType != nil {
|
||||||
|
return *x.MediaType
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Manifest) GetArtifactType() string {
|
||||||
|
if x != nil && x.ArtifactType != nil {
|
||||||
|
return *x.ArtifactType
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Manifest) GetConfig() *Descriptor {
|
||||||
|
if x != nil {
|
||||||
|
return x.Config
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Manifest) GetLayers() []*Descriptor {
|
||||||
|
if x != nil {
|
||||||
|
return x.Layers
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Manifest) GetSubject() *Descriptor {
|
||||||
|
if x != nil {
|
||||||
|
return x.Subject
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Manifest) GetAnnotations() map[string]string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Annotations
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_oci_manifest_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_oci_manifest_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x12, 0x6f, 0x63, 0x69, 0x2f, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x2e, 0x70,
|
||||||
|
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x1a, 0x14, 0x6f, 0x63,
|
||||||
|
0x69, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f,
|
||||||
|
0x74, 0x6f, 0x1a, 0x13, 0x6f, 0x63, 0x69, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x65,
|
||||||
|
0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc2, 0x03, 0x0a, 0x08, 0x4d, 0x61, 0x6e, 0x69,
|
||||||
|
0x66, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x09, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x65,
|
||||||
|
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31,
|
||||||
|
0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x52, 0x09, 0x56, 0x65, 0x72, 0x73,
|
||||||
|
0x69, 0x6f, 0x6e, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x09, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x54, 0x79,
|
||||||
|
0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x4d, 0x65, 0x64, 0x69,
|
||||||
|
0x61, 0x54, 0x79, 0x70, 0x65, 0x88, 0x01, 0x01, 0x12, 0x27, 0x0a, 0x0c, 0x41, 0x72, 0x74, 0x69,
|
||||||
|
0x66, 0x61, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01,
|
||||||
|
0x52, 0x0c, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x88, 0x01,
|
||||||
|
0x01, 0x12, 0x2a, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||||
|
0x0b, 0x32, 0x12, 0x2e, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72,
|
||||||
|
0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2a, 0x0a,
|
||||||
|
0x06, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e,
|
||||||
|
0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
|
||||||
|
0x72, 0x52, 0x06, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x31, 0x0a, 0x07, 0x53, 0x75, 0x62,
|
||||||
|
0x6a, 0x65, 0x63, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6f, 0x63, 0x69,
|
||||||
|
0x5f, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x48, 0x02,
|
||||||
|
0x52, 0x07, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x88, 0x01, 0x01, 0x12, 0x43, 0x0a, 0x0b,
|
||||||
|
0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28,
|
||||||
|
0x0b, 0x32, 0x21, 0x2e, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x6e, 0x69, 0x66,
|
||||||
|
0x65, 0x73, 0x74, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45,
|
||||||
|
0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
|
0x73, 0x1a, 0x3e, 0x0a, 0x10, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
|
||||||
|
0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
|
||||||
|
0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||||
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
|
||||||
|
0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x54, 0x79, 0x70, 0x65, 0x42,
|
||||||
|
0x0f, 0x0a, 0x0d, 0x5f, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65,
|
||||||
|
0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x62, 0x06, 0x70, 0x72,
|
||||||
|
0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_oci_manifest_proto_rawDescOnce sync.Once
|
||||||
|
file_oci_manifest_proto_rawDescData = file_oci_manifest_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_oci_manifest_proto_rawDescGZIP() []byte {
|
||||||
|
file_oci_manifest_proto_rawDescOnce.Do(func() {
|
||||||
|
file_oci_manifest_proto_rawDescData = protoimpl.X.CompressGZIP(file_oci_manifest_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_oci_manifest_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_oci_manifest_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||||
|
var file_oci_manifest_proto_goTypes = []interface{}{
|
||||||
|
(*Manifest)(nil), // 0: oci_v1.Manifest
|
||||||
|
nil, // 1: oci_v1.Manifest.AnnotationsEntry
|
||||||
|
(*Versioned)(nil), // 2: oci_v1.Versioned
|
||||||
|
(*Descriptor)(nil), // 3: oci_v1.Descriptor
|
||||||
|
}
|
||||||
|
var file_oci_manifest_proto_depIdxs = []int32{
|
||||||
|
2, // 0: oci_v1.Manifest.Versioned:type_name -> oci_v1.Versioned
|
||||||
|
3, // 1: oci_v1.Manifest.Config:type_name -> oci_v1.Descriptor
|
||||||
|
3, // 2: oci_v1.Manifest.Layers:type_name -> oci_v1.Descriptor
|
||||||
|
3, // 3: oci_v1.Manifest.Subject:type_name -> oci_v1.Descriptor
|
||||||
|
1, // 4: oci_v1.Manifest.Annotations:type_name -> oci_v1.Manifest.AnnotationsEntry
|
||||||
|
5, // [5:5] is the sub-list for method output_type
|
||||||
|
5, // [5:5] is the sub-list for method input_type
|
||||||
|
5, // [5:5] is the sub-list for extension type_name
|
||||||
|
5, // [5:5] is the sub-list for extension extendee
|
||||||
|
0, // [0:5] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_oci_manifest_proto_init() }
|
||||||
|
func file_oci_manifest_proto_init() {
|
||||||
|
if File_oci_manifest_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
file_oci_descriptor_proto_init()
|
||||||
|
file_oci_versioned_proto_init()
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_oci_manifest_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*Manifest); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_oci_manifest_proto_msgTypes[0].OneofWrappers = []interface{}{}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_oci_manifest_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 2,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_oci_manifest_proto_goTypes,
|
||||||
|
DependencyIndexes: file_oci_manifest_proto_depIdxs,
|
||||||
|
MessageInfos: file_oci_manifest_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_oci_manifest_proto = out.File
|
||||||
|
file_oci_manifest_proto_rawDesc = nil
|
||||||
|
file_oci_manifest_proto_goTypes = nil
|
||||||
|
file_oci_manifest_proto_depIdxs = nil
|
||||||
|
}
|
1521
pkg/meta/proto/gen/meta.pb.go
Normal file
1521
pkg/meta/proto/gen/meta.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
142
pkg/meta/proto/gen/versioned.pb.go
Normal file
142
pkg/meta/proto/gen/versioned.pb.go
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.31.0
|
||||||
|
// protoc v4.24.4
|
||||||
|
// source: oci/versioned.proto
|
||||||
|
|
||||||
|
package gen
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Versioned struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
SchemaVersion int32 `protobuf:"varint,1,opt,name=SchemaVersion,proto3" json:"SchemaVersion,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Versioned) Reset() {
|
||||||
|
*x = Versioned{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_oci_versioned_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Versioned) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Versioned) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Versioned) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_oci_versioned_proto_msgTypes[0]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Versioned.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Versioned) Descriptor() ([]byte, []int) {
|
||||||
|
return file_oci_versioned_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Versioned) GetSchemaVersion() int32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.SchemaVersion
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_oci_versioned_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_oci_versioned_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x13, 0x6f, 0x63, 0x69, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x2e,
|
||||||
|
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x6f, 0x63, 0x69, 0x5f, 0x76, 0x31, 0x22, 0x31, 0x0a,
|
||||||
|
0x09, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x63,
|
||||||
|
0x68, 0x65, 0x6d, 0x61, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
|
0x05, 0x52, 0x0d, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
|
||||||
|
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_oci_versioned_proto_rawDescOnce sync.Once
|
||||||
|
file_oci_versioned_proto_rawDescData = file_oci_versioned_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_oci_versioned_proto_rawDescGZIP() []byte {
|
||||||
|
file_oci_versioned_proto_rawDescOnce.Do(func() {
|
||||||
|
file_oci_versioned_proto_rawDescData = protoimpl.X.CompressGZIP(file_oci_versioned_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_oci_versioned_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_oci_versioned_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||||
|
var file_oci_versioned_proto_goTypes = []interface{}{
|
||||||
|
(*Versioned)(nil), // 0: oci_v1.Versioned
|
||||||
|
}
|
||||||
|
var file_oci_versioned_proto_depIdxs = []int32{
|
||||||
|
0, // [0:0] is the sub-list for method output_type
|
||||||
|
0, // [0:0] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_oci_versioned_proto_init() }
|
||||||
|
func file_oci_versioned_proto_init() {
|
||||||
|
if File_oci_versioned_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_oci_versioned_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*Versioned); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_oci_versioned_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 1,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_oci_versioned_proto_goTypes,
|
||||||
|
DependencyIndexes: file_oci_versioned_proto_depIdxs,
|
||||||
|
MessageInfos: file_oci_versioned_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_oci_versioned_proto = out.File
|
||||||
|
file_oci_versioned_proto_rawDesc = nil
|
||||||
|
file_oci_versioned_proto_goTypes = nil
|
||||||
|
file_oci_versioned_proto_depIdxs = nil
|
||||||
|
}
|
115
pkg/meta/proto/meta/meta.proto
Normal file
115
pkg/meta/proto/meta/meta.proto
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package meta_v1;
|
||||||
|
|
||||||
|
import "oci/config.proto";
|
||||||
|
import "oci/manifest.proto";
|
||||||
|
import "oci/index.proto";
|
||||||
|
import "oci/timestamp.proto";
|
||||||
|
import "oci/descriptor.proto";
|
||||||
|
|
||||||
|
message TagDescriptor {
|
||||||
|
string MediaType = 1;
|
||||||
|
string Digest = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ImageMeta {
|
||||||
|
string MediaType = 1;
|
||||||
|
repeated ManifestMeta Manifests = 2;
|
||||||
|
optional IndexMeta Index = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ManifestMeta {
|
||||||
|
string Digest = 1;
|
||||||
|
int64 Size = 2;
|
||||||
|
oci_v1.Manifest Manifest = 3;
|
||||||
|
oci_v1.Image Config = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message IndexMeta {
|
||||||
|
string Digest = 1;
|
||||||
|
int64 Size = 2;
|
||||||
|
oci_v1.Index Index = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RepoLastUpdatedImage {
|
||||||
|
optional google.protobuf.Timestamp LastUpdated = 1;
|
||||||
|
string MediaType = 2;
|
||||||
|
string Digest = 3;
|
||||||
|
string Tag = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RepoMeta {
|
||||||
|
string Name = 1;
|
||||||
|
map<string, TagDescriptor> Tags = 2;
|
||||||
|
|
||||||
|
map<string, DescriptorStatistics> Statistics = 3;
|
||||||
|
map<string, ManifestSignatures> Signatures = 4;
|
||||||
|
map<string, ReferrersInfo> Referrers = 5;
|
||||||
|
|
||||||
|
bool IsStarred = 6;
|
||||||
|
bool IsBookmarked = 7;
|
||||||
|
int32 Rank = 8;
|
||||||
|
|
||||||
|
int32 Stars = 9;
|
||||||
|
|
||||||
|
int32 Size = 10;
|
||||||
|
repeated string Vendors = 11;
|
||||||
|
repeated oci_v1.Platform Platforms = 12;
|
||||||
|
optional RepoLastUpdatedImage LastUpdatedImage = 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RepoBlobs {
|
||||||
|
string Name = 1;
|
||||||
|
map<string, BlobInfo> Blobs = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for example this is a manifest and it has a config, and layers
|
||||||
|
// or index and has manifests
|
||||||
|
message BlobInfo {
|
||||||
|
int64 Size = 1;
|
||||||
|
repeated string Vendors = 2;
|
||||||
|
repeated string SubBlobs = 3;
|
||||||
|
repeated oci_v1.Platform Platforms = 4;
|
||||||
|
|
||||||
|
optional google.protobuf.Timestamp LastUpdated = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DescriptorStatistics {
|
||||||
|
int32 DownloadCount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReferrersInfo {
|
||||||
|
repeated ReferrerInfo list = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReferrerInfo {
|
||||||
|
string Digest = 1;
|
||||||
|
int64 Count = 2;
|
||||||
|
string MediaType = 3;
|
||||||
|
string ArtifactType = 4;
|
||||||
|
int64 Size = 5;
|
||||||
|
|
||||||
|
map<string, string> Annotations = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ManifestSignatures {
|
||||||
|
map<string, SignaturesInfo> map = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SignaturesInfo {
|
||||||
|
repeated SignatureInfo list = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SignatureInfo {
|
||||||
|
string SignatureManifestDigest = 1;
|
||||||
|
repeated LayersInfo LayersInfo = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LayersInfo {
|
||||||
|
string LayerDigest = 1;
|
||||||
|
bytes LayerContent = 2;
|
||||||
|
string SignatureKey = 3;
|
||||||
|
string Signer = 4;
|
||||||
|
|
||||||
|
google.protobuf.Timestamp Date = 5;
|
||||||
|
}
|
45
pkg/meta/proto/oci/config.proto
Normal file
45
pkg/meta/proto/oci/config.proto
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package oci_v1;
|
||||||
|
|
||||||
|
import "oci/timestamp.proto";
|
||||||
|
import "oci/descriptor.proto";
|
||||||
|
|
||||||
|
// https://github.com/opencontainers/image-spec/blob/main/specs-go/v1/config.go
|
||||||
|
|
||||||
|
message Image {
|
||||||
|
optional google.protobuf.Timestamp Created = 1;
|
||||||
|
optional string Author = 2;
|
||||||
|
Platform Platform = 3;
|
||||||
|
optional ImageConfig Config = 4;
|
||||||
|
optional RootFS RootFS = 5;
|
||||||
|
repeated History History = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ImageConfig {
|
||||||
|
map <string,EmptyMessage> ExposedPorts = 1;
|
||||||
|
map <string,EmptyMessage> Volumes = 2;
|
||||||
|
map <string,string> Labels = 3;
|
||||||
|
string User = 4;
|
||||||
|
repeated string Env = 5;
|
||||||
|
repeated string Entrypoint = 6;
|
||||||
|
repeated string Cmd = 7;
|
||||||
|
optional string WorkingDir = 8;
|
||||||
|
optional string StopSignal = 9;
|
||||||
|
bool ArgsEscaped = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RootFS {
|
||||||
|
string Type = 1;
|
||||||
|
repeated string DiffIDs = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message History {
|
||||||
|
optional google.protobuf.Timestamp Created = 1;
|
||||||
|
|
||||||
|
optional string CreatedBy = 2;
|
||||||
|
optional string Author = 3;
|
||||||
|
optional string Comment = 4;
|
||||||
|
optional bool EmptyLayer = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EmptyMessage{}
|
23
pkg/meta/proto/oci/descriptor.proto
Normal file
23
pkg/meta/proto/oci/descriptor.proto
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package oci_v1;
|
||||||
|
|
||||||
|
// https://github.com/opencontainers/image-spec/blob/main/specs-go/v1/descriptor.go
|
||||||
|
|
||||||
|
message Descriptor {
|
||||||
|
string MediaType = 1;
|
||||||
|
string Digest = 2;
|
||||||
|
int64 Size = 3;
|
||||||
|
repeated string URLs = 4;
|
||||||
|
bytes Data = 5;
|
||||||
|
optional Platform Platform = 6;
|
||||||
|
optional string ArtifactType = 7;
|
||||||
|
map <string,string> Annotations = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Platform {
|
||||||
|
string Architecture = 1;
|
||||||
|
string OS = 2;
|
||||||
|
optional string OSVersion = 3;
|
||||||
|
repeated string OSFeatures = 4;
|
||||||
|
optional string Variant = 5;
|
||||||
|
}
|
16
pkg/meta/proto/oci/index.proto
Normal file
16
pkg/meta/proto/oci/index.proto
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package oci_v1;
|
||||||
|
|
||||||
|
import "oci/descriptor.proto";
|
||||||
|
import "oci/versioned.proto";
|
||||||
|
|
||||||
|
// https://github.com/opencontainers/image-spec/blob/main/specs-go/v1/index.go
|
||||||
|
|
||||||
|
message Index {
|
||||||
|
Versioned Versioned = 1;
|
||||||
|
optional string MediaType = 2;
|
||||||
|
optional string ArtifactType = 3;
|
||||||
|
repeated Descriptor Manifests = 4;
|
||||||
|
optional Descriptor Subject = 5;
|
||||||
|
map<string,string> Annotations = 6;
|
||||||
|
}
|
17
pkg/meta/proto/oci/manifest.proto
Normal file
17
pkg/meta/proto/oci/manifest.proto
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package oci_v1;
|
||||||
|
|
||||||
|
import "oci/descriptor.proto";
|
||||||
|
import "oci/versioned.proto";
|
||||||
|
|
||||||
|
// https://github.com/opencontainers/image-spec/blob/main/specs-go/v1/manifest.go
|
||||||
|
|
||||||
|
message Manifest {
|
||||||
|
Versioned Versioned = 1;
|
||||||
|
optional string MediaType = 2;
|
||||||
|
optional string ArtifactType = 3;
|
||||||
|
Descriptor Config = 4;
|
||||||
|
repeated Descriptor Layers = 5;
|
||||||
|
optional Descriptor Subject = 6;
|
||||||
|
map<string,string> Annotations = 7;
|
||||||
|
}
|
144
pkg/meta/proto/oci/timestamp.proto
Normal file
144
pkg/meta/proto/oci/timestamp.proto
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// https://developers.google.com/protocol-buffers/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package google.protobuf;
|
||||||
|
|
||||||
|
option cc_enable_arenas = true;
|
||||||
|
option go_package = "google.golang.org/protobuf/types/known/timestamppb";
|
||||||
|
option java_package = "com.google.protobuf";
|
||||||
|
option java_outer_classname = "TimestampProto";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option objc_class_prefix = "GPB";
|
||||||
|
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||||
|
|
||||||
|
// A Timestamp represents a point in time independent of any time zone or local
|
||||||
|
// calendar, encoded as a count of seconds and fractions of seconds at
|
||||||
|
// nanosecond resolution. The count is relative to an epoch at UTC midnight on
|
||||||
|
// January 1, 1970, in the proleptic Gregorian calendar which extends the
|
||||||
|
// Gregorian calendar backwards to year one.
|
||||||
|
//
|
||||||
|
// All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap
|
||||||
|
// second table is needed for interpretation, using a [24-hour linear
|
||||||
|
// smear](https://developers.google.com/time/smear).
|
||||||
|
//
|
||||||
|
// The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By
|
||||||
|
// restricting to that range, we ensure that we can convert to and from [RFC
|
||||||
|
// 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.
|
||||||
|
//
|
||||||
|
// # Examples
|
||||||
|
//
|
||||||
|
// Example 1: Compute Timestamp from POSIX `time()`.
|
||||||
|
//
|
||||||
|
// Timestamp timestamp;
|
||||||
|
// timestamp.set_seconds(time(NULL));
|
||||||
|
// timestamp.set_nanos(0);
|
||||||
|
//
|
||||||
|
// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
|
||||||
|
//
|
||||||
|
// struct timeval tv;
|
||||||
|
// gettimeofday(&tv, NULL);
|
||||||
|
//
|
||||||
|
// Timestamp timestamp;
|
||||||
|
// timestamp.set_seconds(tv.tv_sec);
|
||||||
|
// timestamp.set_nanos(tv.tv_usec * 1000);
|
||||||
|
//
|
||||||
|
// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
|
||||||
|
//
|
||||||
|
// FILETIME ft;
|
||||||
|
// GetSystemTimeAsFileTime(&ft);
|
||||||
|
// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
|
||||||
|
//
|
||||||
|
// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
|
||||||
|
// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
|
||||||
|
// Timestamp timestamp;
|
||||||
|
// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
|
||||||
|
// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
|
||||||
|
//
|
||||||
|
// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
|
||||||
|
//
|
||||||
|
// long millis = System.currentTimeMillis();
|
||||||
|
//
|
||||||
|
// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
|
||||||
|
// .setNanos((int) ((millis % 1000) * 1000000)).build();
|
||||||
|
//
|
||||||
|
// Example 5: Compute Timestamp from Java `Instant.now()`.
|
||||||
|
//
|
||||||
|
// Instant now = Instant.now();
|
||||||
|
//
|
||||||
|
// Timestamp timestamp =
|
||||||
|
// Timestamp.newBuilder().setSeconds(now.getEpochSecond())
|
||||||
|
// .setNanos(now.getNano()).build();
|
||||||
|
//
|
||||||
|
// Example 6: Compute Timestamp from current time in Python.
|
||||||
|
//
|
||||||
|
// timestamp = Timestamp()
|
||||||
|
// timestamp.GetCurrentTime()
|
||||||
|
//
|
||||||
|
// # JSON Mapping
|
||||||
|
//
|
||||||
|
// In JSON format, the Timestamp type is encoded as a string in the
|
||||||
|
// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the
|
||||||
|
// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z"
|
||||||
|
// where {year} is always expressed using four digits while {month}, {day},
|
||||||
|
// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
|
||||||
|
// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
|
||||||
|
// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
|
||||||
|
// is required. A proto3 JSON serializer should always use UTC (as indicated by
|
||||||
|
// "Z") when printing the Timestamp type and a proto3 JSON parser should be
|
||||||
|
// able to accept both UTC and other timezones (as indicated by an offset).
|
||||||
|
//
|
||||||
|
// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
|
||||||
|
// 01:30 UTC on January 15, 2017.
|
||||||
|
//
|
||||||
|
// In JavaScript, one can convert a Date object to this format using the
|
||||||
|
// standard
|
||||||
|
// [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
|
||||||
|
// method. In Python, a standard `datetime.datetime` object can be converted
|
||||||
|
// to this format using
|
||||||
|
// [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with
|
||||||
|
// the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
|
||||||
|
// the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
||||||
|
// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()
|
||||||
|
// ) to obtain a formatter capable of generating timestamps in this format.
|
||||||
|
//
|
||||||
|
message Timestamp {
|
||||||
|
// Represents seconds of UTC time since Unix epoch
|
||||||
|
// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
|
||||||
|
// 9999-12-31T23:59:59Z inclusive.
|
||||||
|
int64 seconds = 1;
|
||||||
|
|
||||||
|
// Non-negative fractions of a second at nanosecond resolution. Negative
|
||||||
|
// second values with fractions must still have non-negative nanos values
|
||||||
|
// that count forward in time. Must be from 0 to 999,999,999
|
||||||
|
// inclusive.
|
||||||
|
int32 nanos = 2;
|
||||||
|
}
|
8
pkg/meta/proto/oci/versioned.proto
Normal file
8
pkg/meta/proto/oci/versioned.proto
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package oci_v1;
|
||||||
|
|
||||||
|
// https://github.com/opencontainers/image-spec/blob/main/specs-go/versioned.go
|
||||||
|
|
||||||
|
message Versioned {
|
||||||
|
int32 SchemaVersion = 1;
|
||||||
|
}
|
@ -5,18 +5,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
godigest "github.com/opencontainers/go-digest"
|
godigest "github.com/opencontainers/go-digest"
|
||||||
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DetailedRepoMeta is a auxiliary structure used for sorting RepoMeta arrays by information
|
|
||||||
// that's not directly available in the RepoMetadata structure (ex. that needs to be calculated
|
|
||||||
// by iterating the manifests, etc.)
|
|
||||||
type DetailedRepoMeta struct {
|
|
||||||
RepoMetadata
|
|
||||||
Rank int
|
|
||||||
Downloads int
|
|
||||||
UpdateTime time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used to model changes to an object after a call to the DB.
|
// Used to model changes to an object after a call to the DB.
|
||||||
type ToggleState int
|
type ToggleState int
|
||||||
|
|
||||||
@ -27,23 +18,109 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
FilterFunc func(repoMeta RepoMetadata, manifestMeta ManifestMetadata) bool
|
// Currently imageMeta applied for indexes is applied for each manifest individually so imageMeta.manifests
|
||||||
FilterRepoFunc func(repoMeta RepoMetadata) bool
|
// contains just 1 manifest.
|
||||||
|
FilterFunc func(repoMeta RepoMeta, imageMeta ImageMeta) bool
|
||||||
|
FilterRepoNameFunc func(repo string) bool
|
||||||
|
FilterFullRepoFunc func(repoMeta RepoMeta) bool
|
||||||
|
FilterRepoTagFunc func(repo, tag string) bool
|
||||||
|
)
|
||||||
|
|
||||||
|
func AcceptAllRepoNames(repo string) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func AcceptAllRepoMeta(repoMeta RepoMeta) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func AcceptAllRepoTag(repo, tag string) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func AcceptAllImageMeta(repoMeta RepoMeta, imageMeta ImageMeta) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLatestImageDigests(repoMetaList []RepoMeta) []string {
|
||||||
|
digests := make([]string, 0, len(repoMetaList))
|
||||||
|
|
||||||
|
for i := range repoMetaList {
|
||||||
|
if repoMetaList[i].LastUpdatedImage != nil {
|
||||||
|
digests = append(digests, repoMetaList[i].LastUpdatedImage.Digest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return digests
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
ImageDigest = string
|
||||||
)
|
)
|
||||||
|
|
||||||
type MetaDB interface { //nolint:interfacebloat
|
type MetaDB interface { //nolint:interfacebloat
|
||||||
UserDB
|
UserDB
|
||||||
|
|
||||||
|
SetImageMeta(digest godigest.Digest, imageMeta ImageMeta) error
|
||||||
|
|
||||||
|
// SetRepoReference sets the given image data to the repo metadata.
|
||||||
|
SetRepoReference(repo string, reference string, imageMeta ImageMeta) error
|
||||||
|
|
||||||
|
// SearchRepos searches for repos given a search string
|
||||||
|
SearchRepos(ctx context.Context, searchText string) ([]RepoMeta, error)
|
||||||
|
|
||||||
|
// SearchTags searches for images(repo:tag) given a search string
|
||||||
|
SearchTags(ctx context.Context, searchText string) ([]FullImageMeta, error)
|
||||||
|
|
||||||
|
// FilterTags filters for images given a filter function
|
||||||
|
FilterTags(ctx context.Context, filterRepoTag FilterRepoTagFunc, filterFunc FilterFunc,
|
||||||
|
) ([]FullImageMeta, error)
|
||||||
|
|
||||||
|
// FilterRepos filters for repos given a filter function
|
||||||
|
FilterRepos(ctx context.Context, rankName FilterRepoNameFunc, filterFunc FilterFullRepoFunc,
|
||||||
|
) ([]RepoMeta, error)
|
||||||
|
|
||||||
|
// GetRepoMeta returns the full information about a repo
|
||||||
|
GetRepoMeta(ctx context.Context, repo string) (RepoMeta, error)
|
||||||
|
|
||||||
|
// GetFullImageMeta returns the full information about an image
|
||||||
|
GetFullImageMeta(ctx context.Context, repo string, tag string) (FullImageMeta, error)
|
||||||
|
|
||||||
|
// GetImageMeta returns the raw information about an image
|
||||||
|
GetImageMeta(digest godigest.Digest) (ImageMeta, error)
|
||||||
|
|
||||||
|
// GetMultipleRepoMeta returns information about all repositories as map[string]RepoMetadata filtered by the filter
|
||||||
|
// function
|
||||||
|
GetMultipleRepoMeta(ctx context.Context, filter func(repoMeta RepoMeta) bool) (
|
||||||
|
[]RepoMeta, error)
|
||||||
|
|
||||||
|
// AddManifestSignature adds signature metadata to a given manifest in the database
|
||||||
|
AddManifestSignature(repo string, signedManifestDigest godigest.Digest, sm SignatureMetadata) error
|
||||||
|
|
||||||
|
// DeleteSignature deletes signature metadata to a given manifest from the database
|
||||||
|
DeleteSignature(repo string, signedManifestDigest godigest.Digest, sigMeta SignatureMetadata) error
|
||||||
|
|
||||||
|
// UpdateSignaturesValidity checks and updates signatures validity of a given manifest
|
||||||
|
UpdateSignaturesValidity(repo string, manifestDigest godigest.Digest) error
|
||||||
|
|
||||||
// IncrementRepoStars adds 1 to the star count of an image
|
// IncrementRepoStars adds 1 to the star count of an image
|
||||||
IncrementRepoStars(repo string) error
|
IncrementRepoStars(repo string) error
|
||||||
|
|
||||||
// IncrementRepoStars subtracts 1 from the star count of an image
|
// DecrementRepoStars subtracts 1 from the star count of an image
|
||||||
DecrementRepoStars(repo string) error
|
DecrementRepoStars(repo string) error
|
||||||
|
|
||||||
// GetRepoStars returns the total number of stars a repo has
|
// SetRepoMeta returns RepoMetadata of a repo from the database
|
||||||
GetRepoStars(repo string) (int, error)
|
SetRepoMeta(repo string, repoMeta RepoMeta) error
|
||||||
|
|
||||||
// SetRepoReference sets the reference of a manifest in the tag list of a repo
|
// GetReferrersInfo returns a list of for all referrers of the given digest that match one of the
|
||||||
SetRepoReference(repo string, reference string, manifestDigest godigest.Digest, mediaType string) error
|
// artifact types.
|
||||||
|
GetReferrersInfo(repo string, referredDigest godigest.Digest, artifactTypes []string) ([]ReferrerInfo, error)
|
||||||
|
|
||||||
|
// IncrementImageDownloads adds 1 to the download count of an image
|
||||||
|
IncrementImageDownloads(repo string, reference string) error
|
||||||
|
|
||||||
|
// FilterImageMeta returns the image data for the given digests
|
||||||
|
FilterImageMeta(ctx context.Context, digests []string) (map[string]ImageMeta, error)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
RemoveRepoReference removes the tag from RepoMetadata if the reference is a tag,
|
RemoveRepoReference removes the tag from RepoMetadata if the reference is a tag,
|
||||||
@ -55,80 +132,12 @@ type MetaDB interface { //nolint:interfacebloat
|
|||||||
*/
|
*/
|
||||||
RemoveRepoReference(repo, reference string, manifestDigest godigest.Digest) error
|
RemoveRepoReference(repo, reference string, manifestDigest godigest.Digest) error
|
||||||
|
|
||||||
// DeleteRepoTag delets the tag from the tag list of a repo
|
// ResetRepoReferences resets all layout specific data (tags, signatures, referrers, etc.) but keep user and image
|
||||||
DeleteRepoTag(repo string, tag string) error
|
// specific metadata such as star count, downloads other statistics
|
||||||
|
ResetRepoReferences(repo string) error
|
||||||
|
|
||||||
// GetRepoMeta returns RepoMetadata of a repo from the database
|
// ResetDB will delete all data in the DB
|
||||||
GetRepoMeta(repo string) (RepoMetadata, error)
|
ResetDB() error
|
||||||
|
|
||||||
// GetUserRepometa return RepoMetadata of a repo from the database along side specific information about the
|
|
||||||
// user
|
|
||||||
GetUserRepoMeta(ctx context.Context, repo string) (RepoMetadata, error)
|
|
||||||
|
|
||||||
// GetRepoMeta returns RepoMetadata of a repo from the database
|
|
||||||
SetRepoMeta(repo string, repoMeta RepoMetadata) error
|
|
||||||
|
|
||||||
// GetMultipleRepoMeta returns information about all repositories as map[string]RepoMetadata filtered by the filter
|
|
||||||
// function
|
|
||||||
GetMultipleRepoMeta(ctx context.Context, filter func(repoMeta RepoMetadata) bool) (
|
|
||||||
[]RepoMetadata, error)
|
|
||||||
|
|
||||||
// SetManifestData sets ManifestData for a given manifest in the database
|
|
||||||
SetManifestData(manifestDigest godigest.Digest, md ManifestData) error
|
|
||||||
|
|
||||||
// GetManifestData return the manifest and its related config
|
|
||||||
GetManifestData(manifestDigest godigest.Digest) (ManifestData, error)
|
|
||||||
|
|
||||||
// GetManifestMeta returns ManifestMetadata for a given manifest from the database
|
|
||||||
GetManifestMeta(repo string, manifestDigest godigest.Digest) (ManifestMetadata, error)
|
|
||||||
|
|
||||||
// GetManifestMeta sets ManifestMetadata for a given manifest in the database
|
|
||||||
SetManifestMeta(repo string, manifestDigest godigest.Digest, mm ManifestMetadata) error
|
|
||||||
|
|
||||||
// SetIndexData sets indexData for a given index in the database
|
|
||||||
SetIndexData(digest godigest.Digest, indexData IndexData) error
|
|
||||||
|
|
||||||
// GetIndexData returns indexData for a given Index from the database
|
|
||||||
GetIndexData(indexDigest godigest.Digest) (IndexData, error)
|
|
||||||
|
|
||||||
// SetReferrer adds a referrer to the referrers list of a manifest inside a repo
|
|
||||||
SetReferrer(repo string, referredDigest godigest.Digest, referrer ReferrerInfo) error
|
|
||||||
|
|
||||||
// SetReferrer delets a referrer to the referrers list of a manifest inside a repo
|
|
||||||
DeleteReferrer(repo string, referredDigest godigest.Digest, referrerDigest godigest.Digest) error
|
|
||||||
|
|
||||||
// GetReferrersInfo returnes a list of for all referrers of the given digest that match one of the
|
|
||||||
// artifact types.
|
|
||||||
GetReferrersInfo(repo string, referredDigest godigest.Digest, artifactTypes []string) (
|
|
||||||
[]ReferrerInfo, error)
|
|
||||||
|
|
||||||
// IncrementManifestDownloads adds 1 to the download count of a manifest
|
|
||||||
IncrementImageDownloads(repo string, reference string) error
|
|
||||||
|
|
||||||
// AddManifestSignature adds signature metadata to a given manifest in the database
|
|
||||||
AddManifestSignature(repo string, signedManifestDigest godigest.Digest, sm SignatureMetadata) error
|
|
||||||
|
|
||||||
// DeleteSignature delets signature metadata to a given manifest from the database
|
|
||||||
DeleteSignature(repo string, signedManifestDigest godigest.Digest, sm SignatureMetadata) error
|
|
||||||
|
|
||||||
// UpdateSignaturesValidity checks and updates signatures validity of a given manifest
|
|
||||||
UpdateSignaturesValidity(repo string, manifestDigest godigest.Digest) error
|
|
||||||
|
|
||||||
// SearchRepos searches for repos given a search string
|
|
||||||
SearchRepos(ctx context.Context, searchText string) (
|
|
||||||
[]RepoMetadata, map[string]ManifestMetadata, map[string]IndexData, error)
|
|
||||||
|
|
||||||
// SearchTags searches for images(repo:tag) given a search string
|
|
||||||
SearchTags(ctx context.Context, searchText string) (
|
|
||||||
[]RepoMetadata, map[string]ManifestMetadata, map[string]IndexData, error)
|
|
||||||
|
|
||||||
// FilterRepos filters for repos given a filter function
|
|
||||||
FilterRepos(ctx context.Context, filter FilterRepoFunc) (
|
|
||||||
[]RepoMetadata, map[string]ManifestMetadata, map[string]IndexData, error)
|
|
||||||
|
|
||||||
// FilterTags filters for images given a filter function
|
|
||||||
FilterTags(ctx context.Context, filterFunc FilterFunc) (
|
|
||||||
[]RepoMetadata, map[string]ManifestMetadata, map[string]IndexData, error)
|
|
||||||
|
|
||||||
PatchDB() error
|
PatchDB() error
|
||||||
|
|
||||||
@ -176,25 +185,78 @@ type UserDB interface { //nolint:interfacebloat
|
|||||||
|
|
||||||
type ImageTrustStore interface {
|
type ImageTrustStore interface {
|
||||||
VerifySignature(
|
VerifySignature(
|
||||||
signatureType string, rawSignature []byte, sigKey string, manifestDigest godigest.Digest, manifestContent []byte,
|
signatureType string, rawSignature []byte, sigKey string, manifestDigest godigest.Digest, imageMeta ImageMeta,
|
||||||
repo string,
|
repo string,
|
||||||
) (string, time.Time, bool, error)
|
) (string, time.Time, bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ManifestMetadata struct {
|
// ImageMeta can store all data related to a image, multiarch or simple. Used for writing imaged to MetaDB.
|
||||||
ManifestBlob []byte
|
type ImageMeta struct {
|
||||||
ConfigBlob []byte
|
MediaType string // MediaType refers to the image descriptor, a manifest or a index (if multiarch)
|
||||||
|
Digest godigest.Digest // Digest refers to the image descriptor, a manifest or a index (if multiarch)
|
||||||
|
Size int64 // Size refers to the image descriptor, a manifest or a index (if multiarch)
|
||||||
|
Index *ispec.Index // If the image is multiarch the Index will be non-nil
|
||||||
|
Manifests []ManifestData // All manifests under the image, 1 for simple images and many for multiarch
|
||||||
|
}
|
||||||
|
|
||||||
|
// ManifestData represents all data related to an image manifests (found from the image contents itself).
|
||||||
|
type ManifestData struct {
|
||||||
|
Size int64
|
||||||
|
Digest godigest.Digest
|
||||||
|
Manifest ispec.Manifest
|
||||||
|
Config ispec.Image
|
||||||
|
}
|
||||||
|
|
||||||
|
type RepoMeta struct {
|
||||||
|
Name string
|
||||||
|
Tags map[string]Descriptor
|
||||||
|
|
||||||
|
Statistics map[string]DescriptorStatistics
|
||||||
|
Signatures map[string]ManifestSignatures
|
||||||
|
Referrers map[string][]ReferrerInfo
|
||||||
|
|
||||||
|
LastUpdatedImage *LastUpdatedImage
|
||||||
|
Platforms []ispec.Platform
|
||||||
|
Vendors []string
|
||||||
|
Size int64
|
||||||
|
|
||||||
|
IsStarred bool
|
||||||
|
IsBookmarked bool
|
||||||
|
Rank int
|
||||||
|
|
||||||
|
StarCount int
|
||||||
DownloadCount int
|
DownloadCount int
|
||||||
|
}
|
||||||
|
|
||||||
|
// FullImageMeta is a condensed structure of all information needed about an image when searching MetaDB.
|
||||||
|
type FullImageMeta struct {
|
||||||
|
Repo string
|
||||||
|
Tag string
|
||||||
|
MediaType string
|
||||||
|
Digest godigest.Digest
|
||||||
|
Size int64
|
||||||
|
Index *ispec.Index
|
||||||
|
Manifests []FullManifestMeta
|
||||||
|
IsStarred bool
|
||||||
|
IsBookmarked bool
|
||||||
|
|
||||||
|
Referrers []ReferrerInfo
|
||||||
|
Statistics DescriptorStatistics
|
||||||
Signatures ManifestSignatures
|
Signatures ManifestSignatures
|
||||||
}
|
}
|
||||||
|
|
||||||
type IndexData struct {
|
type FullManifestMeta struct {
|
||||||
IndexBlob []byte
|
ManifestData
|
||||||
|
|
||||||
|
Referrers []ReferrerInfo
|
||||||
|
Statistics DescriptorStatistics
|
||||||
|
Signatures ManifestSignatures
|
||||||
}
|
}
|
||||||
|
|
||||||
type ManifestData struct {
|
type LastUpdatedImage struct {
|
||||||
ManifestBlob []byte
|
Descriptor
|
||||||
ConfigBlob []byte
|
Tag string
|
||||||
|
LastUpdated *time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
type ReferrerInfo struct {
|
type ReferrerInfo struct {
|
||||||
@ -217,21 +279,6 @@ type DescriptorStatistics struct {
|
|||||||
|
|
||||||
type ManifestSignatures map[string][]SignatureInfo
|
type ManifestSignatures map[string][]SignatureInfo
|
||||||
|
|
||||||
type RepoMetadata struct {
|
|
||||||
Name string
|
|
||||||
Tags map[string]Descriptor
|
|
||||||
|
|
||||||
Statistics map[string]DescriptorStatistics
|
|
||||||
Signatures map[string]ManifestSignatures
|
|
||||||
Referrers map[string][]ReferrerInfo
|
|
||||||
|
|
||||||
IsStarred bool
|
|
||||||
IsBookmarked bool
|
|
||||||
Rank int
|
|
||||||
|
|
||||||
Stars int
|
|
||||||
}
|
|
||||||
|
|
||||||
type LayerInfo struct {
|
type LayerInfo struct {
|
||||||
LayerDigest string
|
LayerDigest string
|
||||||
LayerContent []byte
|
LayerContent []byte
|
||||||
|
@ -127,8 +127,8 @@ func TestVersioningDynamoDB(t *testing.T) {
|
|||||||
Endpoint: os.Getenv("DYNAMODBMOCK_ENDPOINT"),
|
Endpoint: os.Getenv("DYNAMODBMOCK_ENDPOINT"),
|
||||||
Region: "us-east-2",
|
Region: "us-east-2",
|
||||||
RepoMetaTablename: "RepoMetadataTable" + uuid.String(),
|
RepoMetaTablename: "RepoMetadataTable" + uuid.String(),
|
||||||
ManifestDataTablename: "ManifestDataTable" + uuid.String(),
|
RepoBlobsInfoTablename: "RepoBlobsInfoTablename" + uuid.String(),
|
||||||
IndexDataTablename: "IndexDataTable" + uuid.String(),
|
ImageMetaTablename: "ImageMetaTablename" + uuid.String(),
|
||||||
UserDataTablename: "UserDataTable" + uuid.String(),
|
UserDataTablename: "UserDataTable" + uuid.String(),
|
||||||
APIKeyTablename: "ApiKeyTable" + uuid.String(),
|
APIKeyTablename: "ApiKeyTable" + uuid.String(),
|
||||||
VersionTablename: "Version" + uuid.String(),
|
VersionTablename: "Version" + uuid.String(),
|
||||||
@ -142,8 +142,7 @@ func TestVersioningDynamoDB(t *testing.T) {
|
|||||||
dynamoWrapper, err := mdynamodb.New(dynamoClient, params, log)
|
dynamoWrapper, err := mdynamodb.New(dynamoClient, params, log)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
So(dynamoWrapper.ResetManifestDataTable(), ShouldBeNil)
|
So(dynamoWrapper.ResetTable(dynamoWrapper.RepoMetaTablename), ShouldBeNil)
|
||||||
So(dynamoWrapper.ResetRepoMetaTable(), ShouldBeNil)
|
|
||||||
|
|
||||||
Convey("dbVersion is empty", func() {
|
Convey("dbVersion is empty", func() {
|
||||||
err := setDynamoDBVersion(dynamoWrapper.Client, params.VersionTablename, "")
|
err := setDynamoDBVersion(dynamoWrapper.Client, params.VersionTablename, "")
|
||||||
@ -201,7 +200,7 @@ func setDynamoDBVersion(client *dynamodb.Client, versTable, vers string) error {
|
|||||||
":Version": mdAttributeValue,
|
":Version": mdAttributeValue,
|
||||||
},
|
},
|
||||||
Key: map[string]types.AttributeValue{
|
Key: map[string]types.AttributeValue{
|
||||||
"VersionKey": &types.AttributeValueMemberS{
|
"Key": &types.AttributeValueMemberS{
|
||||||
Value: version.DBVersionKey,
|
Value: version.DBVersionKey,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -3,7 +3,6 @@ package storage
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/distribution/registry/storage/driver/factory"
|
"github.com/docker/distribution/registry/storage/driver/factory"
|
||||||
@ -228,10 +227,7 @@ func CheckIsImageSignature(repoName string, manifestBlob []byte, reference strin
|
|||||||
return true, NotationType, manifestContent.Subject.Digest, nil
|
return true, NotationType, manifestContent.Subject.Digest, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// check cosign
|
if tag := reference; zcommon.IsCosignTag(reference) {
|
||||||
cosignTagRule := regexp.MustCompile(`sha256\-.+\.sig`)
|
|
||||||
|
|
||||||
if tag := reference; cosignTagRule.MatchString(reference) {
|
|
||||||
prefixLen := len("sha256-")
|
prefixLen := len("sha256-")
|
||||||
digestLen := 64
|
digestLen := 64
|
||||||
signedImageManifestDigestEncoded := tag[prefixLen : prefixLen+digestLen]
|
signedImageManifestDigestEncoded := tag[prefixLen : prefixLen+digestLen]
|
||||||
|
@ -211,3 +211,35 @@ func GenerateRandomName() (string, int64) {
|
|||||||
|
|
||||||
return string(randomBytes), seed
|
return string(randomBytes), seed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AccumulateField[R any, T any](list []T, accFunc func(T) R) []R {
|
||||||
|
result := make([]R, 0, len(list))
|
||||||
|
|
||||||
|
for i := range list {
|
||||||
|
result = append(result, accFunc(list[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContainSameElements[T comparable](list1, list2 []T) bool {
|
||||||
|
if len(list1) != len(list2) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
count1 := map[T]int{}
|
||||||
|
count2 := map[T]int{}
|
||||||
|
|
||||||
|
for i := range list1 {
|
||||||
|
count1[list1[i]]++
|
||||||
|
count2[list2[i]]++
|
||||||
|
}
|
||||||
|
|
||||||
|
for key := range count1 {
|
||||||
|
if count1[key] != count2[key] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
@ -387,7 +387,7 @@ func GetRandomMultiarchImage(reference string) (image.MultiarchImage, error) {
|
|||||||
index.SchemaVersion = 2
|
index.SchemaVersion = 2
|
||||||
|
|
||||||
return image.MultiarchImage{
|
return image.MultiarchImage{
|
||||||
Index: index, Images: images, Reference: reference,
|
Index: index, Images: images,
|
||||||
}, err
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/opencontainers/image-spec/specs-go"
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
|
||||||
|
mTypes "zotregistry.io/zot/pkg/meta/types"
|
||||||
storageConstants "zotregistry.io/zot/pkg/storage/constants"
|
storageConstants "zotregistry.io/zot/pkg/storage/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -48,6 +49,9 @@ type ConfigBuilder interface {
|
|||||||
// an OCI artifact.
|
// an OCI artifact.
|
||||||
// (see: https://github.com/opencontainers/image-spec/blob/main/manifest.md#guidelines-for-artifact-usage)
|
// (see: https://github.com/opencontainers/image-spec/blob/main/manifest.md#guidelines-for-artifact-usage)
|
||||||
ArtifactConfig(artifactType string) ManifestBuilder
|
ArtifactConfig(artifactType string) ManifestBuilder
|
||||||
|
// PlatformConfig is used when we're interesting in specifying only the platform of a manifest.
|
||||||
|
// Other fields of the config are random.
|
||||||
|
PlatformConfig(architecture, os string) ManifestBuilder
|
||||||
// DefaultConfig sets the default config, platform linux/amd64.
|
// DefaultConfig sets the default config, platform linux/amd64.
|
||||||
DefaultConfig() ManifestBuilder
|
DefaultConfig() ManifestBuilder
|
||||||
// CustomConfigBlob will set a custom blob as the image config without other checks.
|
// CustomConfigBlob will set a custom blob as the image config without other checks.
|
||||||
@ -92,13 +96,17 @@ type Image struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (img *Image) Digest() godigest.Digest {
|
func (img *Image) Digest() godigest.Digest {
|
||||||
|
if img.ManifestDescriptor.Digest != "" {
|
||||||
|
return img.ManifestDescriptor.Digest
|
||||||
|
}
|
||||||
|
|
||||||
|
// when we'll migrate all code to the new format of creating images we can replace this with
|
||||||
|
// the value from manifestDescriptor
|
||||||
blob, err := json.Marshal(img.Manifest)
|
blob, err := json.Marshal(img.Manifest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("unreachable: ispec.Manifest should always be marshable")
|
panic("unreachable: ispec.Manifest should always be marshable")
|
||||||
}
|
}
|
||||||
|
|
||||||
// when we'll migrate all code to the new format of creating images we can replace this with
|
|
||||||
// the value from manifestDescriptor
|
|
||||||
return godigest.FromBytes(blob)
|
return godigest.FromBytes(blob)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,6 +114,16 @@ func (img *Image) DigestStr() string {
|
|||||||
return img.Digest().String()
|
return img.Digest().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (img *Image) Size() int {
|
||||||
|
size := img.ConfigDescriptor.Size + img.ManifestDescriptor.Size
|
||||||
|
|
||||||
|
for _, layer := range img.Manifest.Layers {
|
||||||
|
size += layer.Size
|
||||||
|
}
|
||||||
|
|
||||||
|
return int(size)
|
||||||
|
}
|
||||||
|
|
||||||
func (img Image) Descriptor() ispec.Descriptor {
|
func (img Image) Descriptor() ispec.Descriptor {
|
||||||
return ispec.Descriptor{
|
return ispec.Descriptor{
|
||||||
MediaType: img.ManifestDescriptor.MediaType,
|
MediaType: img.ManifestDescriptor.MediaType,
|
||||||
@ -122,6 +140,22 @@ func (img Image) DescriptorRef() *ispec.Descriptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (img Image) AsImageMeta() mTypes.ImageMeta {
|
||||||
|
return mTypes.ImageMeta{
|
||||||
|
MediaType: img.Manifest.MediaType,
|
||||||
|
Digest: img.ManifestDescriptor.Digest,
|
||||||
|
Size: img.ManifestDescriptor.Size,
|
||||||
|
Manifests: []mTypes.ManifestData{
|
||||||
|
{
|
||||||
|
Size: img.ManifestDescriptor.Size,
|
||||||
|
Digest: img.ManifestDescriptor.Digest,
|
||||||
|
Manifest: img.Manifest,
|
||||||
|
Config: img.Config,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type Layer struct {
|
type Layer struct {
|
||||||
Blob []byte
|
Blob []byte
|
||||||
MediaType string
|
MediaType string
|
||||||
@ -281,6 +315,16 @@ func (ib *BaseImageBuilder) DefaultConfig() ManifestBuilder {
|
|||||||
return ib.ImageConfig(GetDefaultConfig())
|
return ib.ImageConfig(GetDefaultConfig())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ib *BaseImageBuilder) PlatformConfig(arch, os string) ManifestBuilder {
|
||||||
|
conf := GetDefaultConfig()
|
||||||
|
|
||||||
|
conf.Created = RandomDateRef(time.UTC)
|
||||||
|
conf.Author = getRandomAuthor()
|
||||||
|
conf.Platform = ispec.Platform{Architecture: arch, OS: os}
|
||||||
|
|
||||||
|
return ib.ImageConfig(conf)
|
||||||
|
}
|
||||||
|
|
||||||
func (ib *BaseImageBuilder) EmptyConfig() ManifestBuilder {
|
func (ib *BaseImageBuilder) EmptyConfig() ManifestBuilder {
|
||||||
ib.configDescriptor = ispec.DescriptorEmptyJSON
|
ib.configDescriptor = ispec.DescriptorEmptyJSON
|
||||||
|
|
||||||
|
@ -166,16 +166,6 @@ func TestPredefinedImages(t *testing.T) {
|
|||||||
img = CreateRandomVulnerableImageWith().ArtifactType("art.type").Build()
|
img = CreateRandomVulnerableImageWith().ArtifactType("art.type").Build()
|
||||||
So(img.Manifest.ArtifactType, ShouldEqual, "art.type")
|
So(img.Manifest.ArtifactType, ShouldEqual, "art.type")
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("Predefined Multiarch-Images", t, func() {
|
|
||||||
multiArch := CreateRandomMultiarch()
|
|
||||||
So(len(multiArch.Images), ShouldEqual, 3)
|
|
||||||
So(multiArch.Reference, ShouldResemble, multiArch.Digest().String())
|
|
||||||
|
|
||||||
multiArch = CreateVulnerableMultiarch()
|
|
||||||
So(len(multiArch.Images), ShouldEqual, 3)
|
|
||||||
So(multiArch.Reference, ShouldResemble, multiArch.Digest().String())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestImageMethods(t *testing.T) {
|
func TestImageMethods(t *testing.T) {
|
||||||
|
@ -13,7 +13,6 @@ import (
|
|||||||
type MultiarchImage struct {
|
type MultiarchImage struct {
|
||||||
Index ispec.Index
|
Index ispec.Index
|
||||||
Images []Image
|
Images []Image
|
||||||
Reference string
|
|
||||||
|
|
||||||
IndexDescriptor ispec.Descriptor
|
IndexDescriptor ispec.Descriptor
|
||||||
}
|
}
|
||||||
@ -31,17 +30,27 @@ func (mi *MultiarchImage) DigestStr() string {
|
|||||||
return mi.Digest().String()
|
return mi.Digest().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mi *MultiarchImage) IndexData() mTypes.IndexData {
|
func (mi MultiarchImage) AsImageMeta() mTypes.ImageMeta {
|
||||||
indexBlob, err := json.Marshal(mi.Index)
|
index := mi.Index
|
||||||
if err != nil {
|
|
||||||
panic("unreachable: ispec.Index should always be marshable")
|
manifests := make([]mTypes.ManifestData, 0, len(index.Manifests))
|
||||||
|
|
||||||
|
for _, image := range mi.Images {
|
||||||
|
manifests = append(manifests, image.AsImageMeta().Manifests...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return mTypes.IndexData{IndexBlob: indexBlob}
|
return mTypes.ImageMeta{
|
||||||
|
MediaType: ispec.MediaTypeImageIndex,
|
||||||
|
Digest: mi.IndexDescriptor.Digest,
|
||||||
|
Size: mi.IndexDescriptor.Size,
|
||||||
|
Index: &index,
|
||||||
|
Manifests: manifests,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ImagesBuilder interface {
|
type ImagesBuilder interface {
|
||||||
Images(images []Image) MultiarchBuilder
|
Images(images []Image) MultiarchBuilder
|
||||||
|
RandomImages(count int) MultiarchBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
type MultiarchBuilder interface {
|
type MultiarchBuilder interface {
|
||||||
@ -88,6 +97,18 @@ func (mb *BaseMultiarchBuilder) Images(images []Image) MultiarchBuilder {
|
|||||||
return mb
|
return mb
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mb *BaseMultiarchBuilder) RandomImages(count int) MultiarchBuilder {
|
||||||
|
images := make([]Image, count)
|
||||||
|
|
||||||
|
for i := range images {
|
||||||
|
images[i] = CreateRandomImage()
|
||||||
|
}
|
||||||
|
|
||||||
|
mb.images = images
|
||||||
|
|
||||||
|
return mb
|
||||||
|
}
|
||||||
|
|
||||||
func (mb *BaseMultiarchBuilder) Subject(subject *ispec.Descriptor) MultiarchBuilder {
|
func (mb *BaseMultiarchBuilder) Subject(subject *ispec.Descriptor) MultiarchBuilder {
|
||||||
mb.subject = subject
|
mb.subject = subject
|
||||||
|
|
||||||
@ -135,12 +156,9 @@ func (mb *BaseMultiarchBuilder) Build() MultiarchImage {
|
|||||||
|
|
||||||
indexDigest := godigest.FromBytes(indexBlob)
|
indexDigest := godigest.FromBytes(indexBlob)
|
||||||
|
|
||||||
ref := indexDigest.String()
|
|
||||||
|
|
||||||
return MultiarchImage{
|
return MultiarchImage{
|
||||||
Index: index,
|
Index: index,
|
||||||
Images: mb.images,
|
Images: mb.images,
|
||||||
Reference: ref,
|
|
||||||
|
|
||||||
IndexDescriptor: ispec.Descriptor{
|
IndexDescriptor: ispec.Descriptor{
|
||||||
MediaType: ispec.MediaTypeImageIndex,
|
MediaType: ispec.MediaTypeImageIndex,
|
||||||
|
@ -223,10 +223,16 @@ func UploadMultiarchImage(multiImage MultiarchImage, baseURL string, repo, ref s
|
|||||||
}
|
}
|
||||||
|
|
||||||
// put manifest
|
// put manifest
|
||||||
indexBlob, err := json.Marshal(multiImage.Index)
|
indexBlob := multiImage.IndexDescriptor.Data
|
||||||
|
|
||||||
|
if len(indexBlob) == 0 {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
indexBlob, err = json.Marshal(multiImage.Index)
|
||||||
if err = inject.Error(err); err != nil {
|
if err = inject.Error(err); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resp, err := resty.R().
|
resp, err := resty.R().
|
||||||
SetHeader("Content-type", ispec.MediaTypeImageIndex).
|
SetHeader("Content-type", ispec.MediaTypeImageIndex).
|
||||||
|
@ -176,21 +176,3 @@ func GetRandomImageConfig() ([]byte, godigest.Digest) {
|
|||||||
|
|
||||||
return configBlobContent, configBlobDigestRaw
|
return configBlobContent, configBlobDigestRaw
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetIndexBlobWithManifests(manifestDigests []godigest.Digest) ([]byte, error) {
|
|
||||||
manifests := make([]ispec.Descriptor, 0, len(manifestDigests))
|
|
||||||
|
|
||||||
for _, manifestDigest := range manifestDigests {
|
|
||||||
manifests = append(manifests, ispec.Descriptor{
|
|
||||||
Digest: manifestDigest,
|
|
||||||
MediaType: ispec.MediaTypeImageManifest,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
indexContent := ispec.Index{
|
|
||||||
MediaType: ispec.MediaTypeImageIndex,
|
|
||||||
Manifests: manifests,
|
|
||||||
}
|
|
||||||
|
|
||||||
return json.Marshal(indexContent)
|
|
||||||
}
|
|
||||||
|
@ -9,74 +9,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type MetaDBMock struct {
|
type MetaDBMock struct {
|
||||||
SetRepoDescriptionFn func(repo, description string) error
|
|
||||||
|
|
||||||
IncrementRepoStarsFn func(repo string) error
|
|
||||||
|
|
||||||
DecrementRepoStarsFn func(repo string) error
|
|
||||||
|
|
||||||
GetRepoStarsFn func(repo string) (int, error)
|
|
||||||
|
|
||||||
SetRepoLogoFn func(repo string, logoPath string) error
|
|
||||||
|
|
||||||
SetRepoReferenceFn func(repo string, Reference string, manifestDigest godigest.Digest, mediaType string) error
|
|
||||||
|
|
||||||
RemoveRepoReferenceFn func(repo, reference string, manifestDigest godigest.Digest) error
|
|
||||||
|
|
||||||
DeleteRepoTagFn func(repo string, tag string) error
|
|
||||||
|
|
||||||
GetRepoMetaFn func(repo string) (mTypes.RepoMetadata, error)
|
|
||||||
|
|
||||||
GetUserRepoMetaFn func(ctx context.Context, repo string) (mTypes.RepoMetadata, error)
|
|
||||||
|
|
||||||
SetRepoMetaFn func(repo string, repoMeta mTypes.RepoMetadata) error
|
|
||||||
|
|
||||||
GetMultipleRepoMetaFn func(ctx context.Context, filter func(repoMeta mTypes.RepoMetadata) bool) (
|
|
||||||
[]mTypes.RepoMetadata, error)
|
|
||||||
|
|
||||||
GetManifestDataFn func(manifestDigest godigest.Digest) (mTypes.ManifestData, error)
|
|
||||||
|
|
||||||
SetManifestDataFn func(manifestDigest godigest.Digest, mm mTypes.ManifestData) error
|
|
||||||
|
|
||||||
GetManifestMetaFn func(repo string, manifestDigest godigest.Digest) (mTypes.ManifestMetadata, error)
|
|
||||||
|
|
||||||
SetManifestMetaFn func(repo string, manifestDigest godigest.Digest, mm mTypes.ManifestMetadata) error
|
|
||||||
|
|
||||||
SetIndexDataFn func(digest godigest.Digest, indexData mTypes.IndexData) error
|
|
||||||
|
|
||||||
GetIndexDataFn func(indexDigest godigest.Digest) (mTypes.IndexData, error)
|
|
||||||
|
|
||||||
SetReferrerFn func(repo string, referredDigest godigest.Digest, referrer mTypes.ReferrerInfo) error
|
|
||||||
|
|
||||||
DeleteReferrerFn func(repo string, referredDigest godigest.Digest, referrerDigest godigest.Digest) error
|
|
||||||
|
|
||||||
GetReferrersFn func(repo string, referredDigest godigest.Digest) ([]mTypes.Descriptor, error)
|
|
||||||
|
|
||||||
GetReferrersInfoFn func(repo string, referredDigest godigest.Digest, artifactTypes []string) (
|
|
||||||
[]mTypes.ReferrerInfo, error)
|
|
||||||
|
|
||||||
IncrementImageDownloadsFn func(repo string, reference string) error
|
|
||||||
|
|
||||||
UpdateSignaturesValidityFn func(repo string, manifestDigest godigest.Digest) error
|
|
||||||
|
|
||||||
AddManifestSignatureFn func(repo string, signedManifestDigest godigest.Digest, sm mTypes.SignatureMetadata) error
|
|
||||||
|
|
||||||
DeleteSignatureFn func(repo string, signedManifestDigest godigest.Digest, sm mTypes.SignatureMetadata) error
|
|
||||||
|
|
||||||
SearchReposFn func(ctx context.Context, txt string) (
|
|
||||||
[]mTypes.RepoMetadata, map[string]mTypes.ManifestMetadata, map[string]mTypes.IndexData,
|
|
||||||
error)
|
|
||||||
|
|
||||||
SearchTagsFn func(ctx context.Context, txt string) (
|
|
||||||
[]mTypes.RepoMetadata, map[string]mTypes.ManifestMetadata, map[string]mTypes.IndexData,
|
|
||||||
error)
|
|
||||||
|
|
||||||
FilterReposFn func(ctx context.Context, filter mTypes.FilterRepoFunc) (
|
|
||||||
[]mTypes.RepoMetadata, map[string]mTypes.ManifestMetadata, map[string]mTypes.IndexData, error)
|
|
||||||
|
|
||||||
FilterTagsFn func(ctx context.Context, filterFunc mTypes.FilterFunc) (
|
|
||||||
[]mTypes.RepoMetadata, map[string]mTypes.ManifestMetadata, map[string]mTypes.IndexData, error)
|
|
||||||
|
|
||||||
GetStarredReposFn func(ctx context.Context) ([]string, error)
|
GetStarredReposFn func(ctx context.Context) ([]string, error)
|
||||||
|
|
||||||
GetBookmarkedReposFn func(ctx context.Context) ([]string, error)
|
GetBookmarkedReposFn func(ctx context.Context) ([]string, error)
|
||||||
@ -112,6 +44,69 @@ type MetaDBMock struct {
|
|||||||
ImageTrustStoreFn func() mTypes.ImageTrustStore
|
ImageTrustStoreFn func() mTypes.ImageTrustStore
|
||||||
|
|
||||||
SetImageTrustStoreFn func(mTypes.ImageTrustStore)
|
SetImageTrustStoreFn func(mTypes.ImageTrustStore)
|
||||||
|
|
||||||
|
SetRepoReferenceFn func(repo string, reference string, imageMeta mTypes.ImageMeta) error
|
||||||
|
|
||||||
|
SearchReposFn func(ctx context.Context, searchText string,
|
||||||
|
) ([]mTypes.RepoMeta, error)
|
||||||
|
|
||||||
|
SearchTagsFn func(ctx context.Context, searchText string) ([]mTypes.FullImageMeta, error)
|
||||||
|
|
||||||
|
FilterTagFn func(ctx context.Context, filterFunc mTypes.FilterFunc,
|
||||||
|
) ([]mTypes.RepoMeta, map[string]mTypes.ImageMeta, error)
|
||||||
|
|
||||||
|
GetImageMetaFn func(digest godigest.Digest) (mTypes.ImageMeta, error)
|
||||||
|
|
||||||
|
GetMultipleRepoMetaFn func(ctx context.Context, filter func(repoMeta mTypes.RepoMeta) bool,
|
||||||
|
) ([]mTypes.RepoMeta, error)
|
||||||
|
|
||||||
|
FilterReposFn func(ctx context.Context, rankName mTypes.FilterRepoNameFunc,
|
||||||
|
filterFunc mTypes.FilterFullRepoFunc) ([]mTypes.RepoMeta, error)
|
||||||
|
|
||||||
|
IncrementRepoStarsFn func(repo string) error
|
||||||
|
|
||||||
|
DecrementRepoStarsFn func(repo string) error
|
||||||
|
|
||||||
|
SetRepoMetaFn func(repo string, repoMeta mTypes.RepoMeta) error
|
||||||
|
|
||||||
|
DeleteReferrerFn func(repo string, referredDigest godigest.Digest, referrerDigest godigest.Digest) error
|
||||||
|
|
||||||
|
GetReferrersInfoFn func(repo string, referredDigest godigest.Digest, artifactTypes []string,
|
||||||
|
) ([]mTypes.ReferrerInfo, error)
|
||||||
|
|
||||||
|
IncrementImageDownloadsFn func(repo string, reference string) error
|
||||||
|
|
||||||
|
UpdateSignaturesValidityFn func(repo string, manifestDigest godigest.Digest) error
|
||||||
|
|
||||||
|
AddManifestSignatureFn func(repo string, signedManifestDigest godigest.Digest, sygMeta mTypes.SignatureMetadata,
|
||||||
|
) error
|
||||||
|
|
||||||
|
DeleteSignatureFn func(repo string, signedManifestDigest godigest.Digest, sigMeta mTypes.SignatureMetadata) error
|
||||||
|
|
||||||
|
SetImageMetaFn func(digest godigest.Digest, imageMeta mTypes.ImageMeta) error
|
||||||
|
|
||||||
|
FilterTagsFn func(ctx context.Context, filterRepoTag mTypes.FilterRepoTagFunc,
|
||||||
|
filterFunc mTypes.FilterFunc) ([]mTypes.FullImageMeta, error)
|
||||||
|
|
||||||
|
GetRepoMetaFn func(ctx context.Context, repo string) (mTypes.RepoMeta, error)
|
||||||
|
|
||||||
|
FilterImageMetaFn func(ctx context.Context, digests []string) (map[string]mTypes.ImageMeta, error)
|
||||||
|
|
||||||
|
RemoveRepoReferenceFn func(repo, reference string, manifestDigest godigest.Digest) error
|
||||||
|
|
||||||
|
GetFullImageMetaFn func(ctx context.Context, repo string, tag string) (mTypes.FullImageMeta, error)
|
||||||
|
|
||||||
|
ResetRepoReferencesFn func(repo string) error
|
||||||
|
|
||||||
|
ResetDBFn func() error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) ResetDB() error {
|
||||||
|
if sdm.ResetDBFn != nil {
|
||||||
|
return sdm.ResetDBFn()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sdm MetaDBMock) ImageTrustStore() mTypes.ImageTrustStore {
|
func (sdm MetaDBMock) ImageTrustStore() mTypes.ImageTrustStore {
|
||||||
@ -128,221 +123,6 @@ func (sdm MetaDBMock) SetImageTrustStore(imgTrustStore mTypes.ImageTrustStore) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sdm MetaDBMock) SetRepoDescription(repo, description string) error {
|
|
||||||
if sdm.SetRepoDescriptionFn != nil {
|
|
||||||
return sdm.SetRepoDescriptionFn(repo, description)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) IncrementRepoStars(repo string) error {
|
|
||||||
if sdm.IncrementRepoStarsFn != nil {
|
|
||||||
return sdm.IncrementRepoStarsFn(repo)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) DecrementRepoStars(repo string) error {
|
|
||||||
if sdm.DecrementRepoStarsFn != nil {
|
|
||||||
return sdm.DecrementRepoStarsFn(repo)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) GetRepoStars(repo string) (int, error) {
|
|
||||||
if sdm.GetRepoStarsFn != nil {
|
|
||||||
return sdm.GetRepoStarsFn(repo)
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) SetRepoReference(repo string, reference string, manifestDigest godigest.Digest,
|
|
||||||
mediaType string,
|
|
||||||
) error {
|
|
||||||
if sdm.SetRepoReferenceFn != nil {
|
|
||||||
return sdm.SetRepoReferenceFn(repo, reference, manifestDigest, mediaType)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) RemoveRepoReference(repo, reference string, manifestDigest godigest.Digest) error {
|
|
||||||
if sdm.RemoveRepoReferenceFn != nil {
|
|
||||||
return sdm.RemoveRepoReferenceFn(repo, reference, manifestDigest)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) DeleteRepoTag(repo string, tag string) error {
|
|
||||||
if sdm.DeleteRepoTagFn != nil {
|
|
||||||
return sdm.DeleteRepoTagFn(repo, tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) GetRepoMeta(repo string) (mTypes.RepoMetadata, error) {
|
|
||||||
if sdm.GetRepoMetaFn != nil {
|
|
||||||
return sdm.GetRepoMetaFn(repo)
|
|
||||||
}
|
|
||||||
|
|
||||||
return mTypes.RepoMetadata{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) GetUserRepoMeta(ctx context.Context, repo string) (mTypes.RepoMetadata, error) {
|
|
||||||
if sdm.GetUserRepoMetaFn != nil {
|
|
||||||
return sdm.GetUserRepoMetaFn(ctx, repo)
|
|
||||||
}
|
|
||||||
|
|
||||||
return mTypes.RepoMetadata{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) SetRepoMeta(repo string, repoMeta mTypes.RepoMetadata) error {
|
|
||||||
if sdm.SetRepoMetaFn != nil {
|
|
||||||
return sdm.SetRepoMetaFn(repo, repoMeta)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) GetMultipleRepoMeta(ctx context.Context, filter func(repoMeta mTypes.RepoMetadata) bool,
|
|
||||||
) ([]mTypes.RepoMetadata, error) {
|
|
||||||
if sdm.GetMultipleRepoMetaFn != nil {
|
|
||||||
return sdm.GetMultipleRepoMetaFn(ctx, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
return []mTypes.RepoMetadata{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) GetManifestData(manifestDigest godigest.Digest) (mTypes.ManifestData, error) {
|
|
||||||
if sdm.GetManifestDataFn != nil {
|
|
||||||
return sdm.GetManifestDataFn(manifestDigest)
|
|
||||||
}
|
|
||||||
|
|
||||||
return mTypes.ManifestData{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) SetManifestData(manifestDigest godigest.Digest, md mTypes.ManifestData) error {
|
|
||||||
if sdm.SetManifestDataFn != nil {
|
|
||||||
return sdm.SetManifestDataFn(manifestDigest, md)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) GetManifestMeta(repo string, manifestDigest godigest.Digest) (mTypes.ManifestMetadata, error) {
|
|
||||||
if sdm.GetManifestMetaFn != nil {
|
|
||||||
return sdm.GetManifestMetaFn(repo, manifestDigest)
|
|
||||||
}
|
|
||||||
|
|
||||||
return mTypes.ManifestMetadata{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) SetManifestMeta(repo string, manifestDigest godigest.Digest, mm mTypes.ManifestMetadata) error {
|
|
||||||
if sdm.SetManifestMetaFn != nil {
|
|
||||||
return sdm.SetManifestMetaFn(repo, manifestDigest, mm)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) IncrementImageDownloads(repo string, reference string) error {
|
|
||||||
if sdm.IncrementImageDownloadsFn != nil {
|
|
||||||
return sdm.IncrementImageDownloadsFn(repo, reference)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) UpdateSignaturesValidity(repo string, manifestDigest godigest.Digest) error {
|
|
||||||
if sdm.UpdateSignaturesValidityFn != nil {
|
|
||||||
return sdm.UpdateSignaturesValidityFn(repo, manifestDigest)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) AddManifestSignature(repo string, signedManifestDigest godigest.Digest,
|
|
||||||
sm mTypes.SignatureMetadata,
|
|
||||||
) error {
|
|
||||||
if sdm.AddManifestSignatureFn != nil {
|
|
||||||
return sdm.AddManifestSignatureFn(repo, signedManifestDigest, sm)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) DeleteSignature(repo string, signedManifestDigest godigest.Digest,
|
|
||||||
sm mTypes.SignatureMetadata,
|
|
||||||
) error {
|
|
||||||
if sdm.DeleteSignatureFn != nil {
|
|
||||||
return sdm.DeleteSignatureFn(repo, signedManifestDigest, sm)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) SearchRepos(ctx context.Context, searchText string,
|
|
||||||
) ([]mTypes.RepoMetadata, map[string]mTypes.ManifestMetadata, map[string]mTypes.IndexData, error) {
|
|
||||||
if sdm.SearchReposFn != nil {
|
|
||||||
return sdm.SearchReposFn(ctx, searchText)
|
|
||||||
}
|
|
||||||
|
|
||||||
return []mTypes.RepoMetadata{}, map[string]mTypes.ManifestMetadata{},
|
|
||||||
map[string]mTypes.IndexData{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) SearchTags(ctx context.Context, searchText string,
|
|
||||||
) ([]mTypes.RepoMetadata, map[string]mTypes.ManifestMetadata, map[string]mTypes.IndexData, error) {
|
|
||||||
if sdm.SearchTagsFn != nil {
|
|
||||||
return sdm.SearchTagsFn(ctx, searchText)
|
|
||||||
}
|
|
||||||
|
|
||||||
return []mTypes.RepoMetadata{}, map[string]mTypes.ManifestMetadata{},
|
|
||||||
map[string]mTypes.IndexData{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) FilterRepos(ctx context.Context, filter mTypes.FilterRepoFunc,
|
|
||||||
) ([]mTypes.RepoMetadata, map[string]mTypes.ManifestMetadata, map[string]mTypes.IndexData, error) {
|
|
||||||
if sdm.FilterReposFn != nil {
|
|
||||||
return sdm.FilterReposFn(ctx, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
return []mTypes.RepoMetadata{}, map[string]mTypes.ManifestMetadata{},
|
|
||||||
map[string]mTypes.IndexData{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) FilterTags(ctx context.Context, filterFunc mTypes.FilterFunc,
|
|
||||||
) ([]mTypes.RepoMetadata, map[string]mTypes.ManifestMetadata, map[string]mTypes.IndexData, error) {
|
|
||||||
if sdm.FilterTagsFn != nil {
|
|
||||||
return sdm.FilterTagsFn(ctx, filterFunc)
|
|
||||||
}
|
|
||||||
|
|
||||||
return []mTypes.RepoMetadata{}, map[string]mTypes.ManifestMetadata{},
|
|
||||||
map[string]mTypes.IndexData{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) SetIndexData(digest godigest.Digest, indexData mTypes.IndexData) error {
|
|
||||||
if sdm.SetIndexDataFn != nil {
|
|
||||||
return sdm.SetIndexDataFn(digest, indexData)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) GetIndexData(indexDigest godigest.Digest) (mTypes.IndexData, error) {
|
|
||||||
if sdm.GetIndexDataFn != nil {
|
|
||||||
return sdm.GetIndexDataFn(indexDigest)
|
|
||||||
}
|
|
||||||
|
|
||||||
return mTypes.IndexData{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) PatchDB() error {
|
func (sdm MetaDBMock) PatchDB() error {
|
||||||
if sdm.PatchDBFn != nil {
|
if sdm.PatchDBFn != nil {
|
||||||
return sdm.PatchDBFn()
|
return sdm.PatchDBFn()
|
||||||
@ -351,34 +131,6 @@ func (sdm MetaDBMock) PatchDB() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sdm MetaDBMock) SetReferrer(repo string, referredDigest godigest.Digest, referrer mTypes.ReferrerInfo) error {
|
|
||||||
if sdm.SetReferrerFn != nil {
|
|
||||||
return sdm.SetReferrerFn(repo, referredDigest, referrer)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) DeleteReferrer(repo string, referredDigest godigest.Digest,
|
|
||||||
referrerDigest godigest.Digest,
|
|
||||||
) error {
|
|
||||||
if sdm.DeleteReferrerFn != nil {
|
|
||||||
return sdm.DeleteReferrerFn(repo, referredDigest, referrerDigest)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) GetReferrersInfo(repo string, referredDigest godigest.Digest,
|
|
||||||
artifactTypes []string,
|
|
||||||
) ([]mTypes.ReferrerInfo, error) {
|
|
||||||
if sdm.GetReferrersInfoFn != nil {
|
|
||||||
return sdm.GetReferrersInfoFn(repo, referredDigest, artifactTypes)
|
|
||||||
}
|
|
||||||
|
|
||||||
return []mTypes.ReferrerInfo{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sdm MetaDBMock) GetStarredRepos(ctx context.Context) ([]string, error) {
|
func (sdm MetaDBMock) GetStarredRepos(ctx context.Context) ([]string, error) {
|
||||||
if sdm.GetStarredReposFn != nil {
|
if sdm.GetStarredReposFn != nil {
|
||||||
return sdm.GetStarredReposFn(ctx)
|
return sdm.GetStarredReposFn(ctx)
|
||||||
@ -498,3 +250,184 @@ func (sdm MetaDBMock) DeleteUserAPIKey(ctx context.Context, id string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) SetImageMeta(digest godigest.Digest, imageMeta mTypes.ImageMeta) error {
|
||||||
|
if sdm.SetImageMetaFn != nil {
|
||||||
|
return sdm.SetImageMetaFn(digest, imageMeta)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) SetRepoReference(repo string, reference string, imageMeta mTypes.ImageMeta) error {
|
||||||
|
if sdm.SetRepoReferenceFn != nil {
|
||||||
|
return sdm.SetRepoReferenceFn(repo, reference, imageMeta)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) SearchRepos(ctx context.Context, searchText string) ([]mTypes.RepoMeta, error) {
|
||||||
|
if sdm.SearchReposFn != nil {
|
||||||
|
return sdm.SearchReposFn(ctx, searchText)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []mTypes.RepoMeta{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) SearchTags(ctx context.Context, searchText string) ([]mTypes.FullImageMeta, error) {
|
||||||
|
if sdm.SearchTagsFn != nil {
|
||||||
|
return sdm.SearchTagsFn(ctx, searchText)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []mTypes.FullImageMeta{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) FilterTags(ctx context.Context, filterRepoTag mTypes.FilterRepoTagFunc,
|
||||||
|
filterFunc mTypes.FilterFunc,
|
||||||
|
) ([]mTypes.FullImageMeta, error) {
|
||||||
|
if sdm.FilterTagsFn != nil {
|
||||||
|
return sdm.FilterTagsFn(ctx, filterRepoTag, filterFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []mTypes.FullImageMeta{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) GetRepoMeta(ctx context.Context, repo string) (mTypes.RepoMeta, error) {
|
||||||
|
if sdm.GetRepoMetaFn != nil {
|
||||||
|
return sdm.GetRepoMetaFn(ctx, repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
return mTypes.RepoMeta{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) GetImageMeta(digest godigest.Digest) (mTypes.ImageMeta, error) {
|
||||||
|
if sdm.GetImageMetaFn != nil {
|
||||||
|
return sdm.GetImageMetaFn(digest)
|
||||||
|
}
|
||||||
|
|
||||||
|
return mTypes.ImageMeta{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) GetMultipleRepoMeta(ctx context.Context, filter func(repoMeta mTypes.RepoMeta) bool,
|
||||||
|
) ([]mTypes.RepoMeta, error) {
|
||||||
|
if sdm.GetMultipleRepoMetaFn != nil {
|
||||||
|
return sdm.GetMultipleRepoMetaFn(ctx, filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []mTypes.RepoMeta{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) FilterRepos(ctx context.Context, rankName mTypes.FilterRepoNameFunc,
|
||||||
|
filterFunc mTypes.FilterFullRepoFunc,
|
||||||
|
) ([]mTypes.RepoMeta, error) {
|
||||||
|
if sdm.FilterReposFn != nil {
|
||||||
|
return sdm.FilterReposFn(ctx, rankName, filterFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []mTypes.RepoMeta{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) IncrementRepoStars(repo string) error {
|
||||||
|
if sdm.IncrementRepoStarsFn != nil {
|
||||||
|
return sdm.IncrementRepoStarsFn(repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) DecrementRepoStars(repo string) error {
|
||||||
|
if sdm.DecrementRepoStarsFn != nil {
|
||||||
|
return sdm.DecrementRepoStarsFn(repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) SetRepoMeta(repo string, repoMeta mTypes.RepoMeta) error {
|
||||||
|
if sdm.SetRepoMetaFn != nil {
|
||||||
|
return sdm.SetRepoMetaFn(repo, repoMeta)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) GetReferrersInfo(repo string, referredDigest godigest.Digest,
|
||||||
|
artifactTypes []string,
|
||||||
|
) ([]mTypes.ReferrerInfo, error) {
|
||||||
|
if sdm.GetReferrersInfoFn != nil {
|
||||||
|
return sdm.GetReferrersInfoFn(repo, referredDigest, artifactTypes)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []mTypes.ReferrerInfo{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) IncrementImageDownloads(repo string, reference string) error {
|
||||||
|
if sdm.IncrementImageDownloadsFn != nil {
|
||||||
|
return sdm.IncrementImageDownloadsFn(repo, reference)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) UpdateSignaturesValidity(repo string, manifestDigest godigest.Digest) error {
|
||||||
|
if sdm.UpdateSignaturesValidityFn != nil {
|
||||||
|
return sdm.UpdateSignaturesValidityFn(repo, manifestDigest)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) AddManifestSignature(repo string, signedManifestDigest godigest.Digest,
|
||||||
|
sygMeta mTypes.SignatureMetadata,
|
||||||
|
) error {
|
||||||
|
if sdm.AddManifestSignatureFn != nil {
|
||||||
|
return sdm.AddManifestSignatureFn(repo, signedManifestDigest, sygMeta)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) DeleteSignature(repo string, signedManifestDigest godigest.Digest,
|
||||||
|
sigMeta mTypes.SignatureMetadata,
|
||||||
|
) error {
|
||||||
|
if sdm.DeleteSignatureFn != nil {
|
||||||
|
return sdm.DeleteSignatureFn(repo, signedManifestDigest, sigMeta)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) FilterImageMeta(ctx context.Context, digests []string,
|
||||||
|
) (map[string]mTypes.ImageMeta, error) {
|
||||||
|
if sdm.FilterImageMetaFn != nil {
|
||||||
|
return sdm.FilterImageMetaFn(ctx, digests)
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]mTypes.ImageMeta{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) RemoveRepoReference(repo, reference string, manifestDigest godigest.Digest) error {
|
||||||
|
if sdm.RemoveRepoReferenceFn != nil {
|
||||||
|
return sdm.RemoveRepoReferenceFn(repo, reference, manifestDigest)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) GetFullImageMeta(ctx context.Context, repo string, tag string,
|
||||||
|
) (mTypes.FullImageMeta, error) {
|
||||||
|
if sdm.GetFullImageMetaFn != nil {
|
||||||
|
return sdm.GetFullImageMetaFn(ctx, repo, tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
return mTypes.FullImageMeta{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sdm MetaDBMock) ResetRepoReferences(repo string) error {
|
||||||
|
if sdm.ResetRepoReferencesFn != nil {
|
||||||
|
return sdm.ResetRepoReferencesFn(repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -1,110 +1,142 @@
|
|||||||
package ociutils
|
package ociutils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
zerr "zotregistry.io/zot/errors"
|
||||||
mTypes "zotregistry.io/zot/pkg/meta/types"
|
mTypes "zotregistry.io/zot/pkg/meta/types"
|
||||||
|
reqCtx "zotregistry.io/zot/pkg/requestcontext"
|
||||||
imageUtil "zotregistry.io/zot/pkg/test/image-utils"
|
imageUtil "zotregistry.io/zot/pkg/test/image-utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RepoImage struct {
|
type RepoImage struct {
|
||||||
imageUtil.Image
|
imageUtil.Image
|
||||||
Tag string
|
Reference string
|
||||||
Statistics mTypes.DescriptorStatistics
|
Statistics mTypes.DescriptorStatistics
|
||||||
}
|
}
|
||||||
|
|
||||||
type RepoMultiArchImage struct {
|
type RepoMultiArchImage struct {
|
||||||
imageUtil.MultiarchImage
|
imageUtil.MultiarchImage
|
||||||
ImageStatistics map[string]mTypes.DescriptorStatistics
|
ImageStatistics map[string]mTypes.DescriptorStatistics
|
||||||
Tag string
|
Reference string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Repo struct {
|
type Repo struct {
|
||||||
Name string
|
Name string
|
||||||
Images []RepoImage
|
Images []RepoImage
|
||||||
MultiArchImages []RepoMultiArchImage
|
MultiArchImages []RepoMultiArchImage
|
||||||
|
Signatures map[string]mTypes.ManifestSignatures
|
||||||
|
Stars int
|
||||||
IsBookmarked bool
|
IsBookmarked bool
|
||||||
IsStarred bool
|
IsStarred bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMetadataForRepos(repos ...Repo) ([]mTypes.RepoMetadata, map[string]mTypes.ManifestMetadata,
|
func InitializeTestMetaDB(ctx context.Context, metaDB mTypes.MetaDB, repos ...Repo) (context.Context, error) {
|
||||||
map[string]mTypes.IndexData,
|
uac := reqCtx.NewUserAccessControl()
|
||||||
) {
|
uac.SetUsername("test")
|
||||||
var (
|
uacContext := context.WithValue(ctx, reqCtx.GetContextKey(), *uac)
|
||||||
reposMetadata = []mTypes.RepoMetadata{}
|
|
||||||
manifestMetadataMap = map[string]mTypes.ManifestMetadata{}
|
|
||||||
indexDataMap = map[string]mTypes.IndexData{}
|
|
||||||
)
|
|
||||||
|
|
||||||
for _, repo := range repos {
|
err := validateRepos(repos)
|
||||||
repoMeta := mTypes.RepoMetadata{
|
if err != nil {
|
||||||
Name: repo.Name,
|
return uacContext, err
|
||||||
Tags: map[string]mTypes.Descriptor{},
|
|
||||||
Signatures: map[string]mTypes.ManifestSignatures{},
|
|
||||||
Statistics: map[string]mTypes.DescriptorStatistics{},
|
|
||||||
IsStarred: repo.IsStarred,
|
|
||||||
IsBookmarked: repo.IsBookmarked,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, repo := range repos {
|
||||||
|
statistics := map[string]mTypes.DescriptorStatistics{"": {}}
|
||||||
|
|
||||||
for _, image := range repo.Images {
|
for _, image := range repo.Images {
|
||||||
addImageMetaToMetaDB(image, repoMeta, manifestMetadataMap)
|
err := metaDB.SetRepoReference(repo.Name, image.Reference, image.AsImageMeta())
|
||||||
|
if err != nil {
|
||||||
|
return uacContext, err
|
||||||
|
}
|
||||||
|
|
||||||
|
statistics[image.DigestStr()] = image.Statistics
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, multiArch := range repo.MultiArchImages {
|
for _, multiArch := range repo.MultiArchImages {
|
||||||
if multiArch.ImageStatistics == nil {
|
|
||||||
multiArch.ImageStatistics = map[string]mTypes.DescriptorStatistics{}
|
|
||||||
}
|
|
||||||
|
|
||||||
repoMeta.Tags[multiArch.Tag] = mTypes.Descriptor{
|
|
||||||
MediaType: ispec.MediaTypeImageIndex,
|
|
||||||
Digest: multiArch.DigestStr(),
|
|
||||||
}
|
|
||||||
|
|
||||||
repoMeta.Statistics[multiArch.DigestStr()] = multiArch.ImageStatistics[multiArch.DigestStr()]
|
|
||||||
|
|
||||||
for _, image := range multiArch.Images {
|
for _, image := range multiArch.Images {
|
||||||
addImageMetaToMetaDB(RepoImage{
|
err := metaDB.SetRepoReference(repo.Name, image.DigestStr(), image.AsImageMeta())
|
||||||
Image: image,
|
if err != nil {
|
||||||
Statistics: multiArch.ImageStatistics[image.DigestStr()],
|
return uacContext, err
|
||||||
}, repoMeta, manifestMetadataMap)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
indexDataMap[multiArch.IndexDescriptor.Digest.String()] = mTypes.IndexData{
|
statistics[image.DigestStr()] = multiArch.ImageStatistics[image.DigestStr()]
|
||||||
IndexBlob: multiArch.IndexDescriptor.Data,
|
}
|
||||||
|
|
||||||
|
err := metaDB.SetRepoReference(repo.Name, multiArch.Reference, multiArch.AsImageMeta())
|
||||||
|
if err != nil {
|
||||||
|
return uacContext, err
|
||||||
|
}
|
||||||
|
|
||||||
|
statistics[multiArch.DigestStr()] = multiArch.ImageStatistics[multiArch.DigestStr()]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update repo metadata
|
||||||
|
repoMeta, err := metaDB.GetRepoMeta(ctx, repo.Name)
|
||||||
|
if err != nil {
|
||||||
|
return uacContext, err
|
||||||
|
}
|
||||||
|
|
||||||
|
repoMeta.StarCount = repo.Stars
|
||||||
|
repoMeta.IsStarred = repo.IsStarred
|
||||||
|
repoMeta.IsBookmarked = repo.IsBookmarked
|
||||||
|
|
||||||
|
// updateStatistics
|
||||||
|
for key, value := range statistics {
|
||||||
|
repoMeta.Statistics[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// update signatures?
|
||||||
|
for key, value := range repo.Signatures {
|
||||||
|
repoMeta.Signatures[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
err = metaDB.SetRepoMeta(repo.Name, repoMeta)
|
||||||
|
if err != nil {
|
||||||
|
return uacContext, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// User data is set after we create the repo
|
||||||
|
if repo.IsBookmarked {
|
||||||
|
_, err := metaDB.ToggleBookmarkRepo(uacContext, repo.Name)
|
||||||
|
if err != nil {
|
||||||
|
return uacContext, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reposMetadata = append(reposMetadata, repoMeta)
|
if repo.IsStarred {
|
||||||
|
_, err := metaDB.ToggleStarRepo(uacContext, repo.Name)
|
||||||
|
if err != nil {
|
||||||
|
return uacContext, err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return reposMetadata, manifestMetadataMap, indexDataMap
|
return uacContext, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addImageMetaToMetaDB(image RepoImage, repoMeta mTypes.RepoMetadata,
|
func validateRepos(repos []Repo) error {
|
||||||
manifestMetadataMap map[string]mTypes.ManifestMetadata,
|
repoNames := map[string]struct{}{}
|
||||||
) {
|
|
||||||
if image.Tag != "" {
|
|
||||||
repoMeta.Tags[image.Tag] = mTypes.Descriptor{
|
|
||||||
MediaType: ispec.MediaTypeImageManifest,
|
|
||||||
Digest: image.DigestStr(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// here we can do many more checks about the images like check for referrers, signatures but it's not needed yet
|
|
||||||
// I need just the tags for now and the fake signature.
|
|
||||||
|
|
||||||
// This is done just to mark a manifest as signed in the resulted RepoMeta
|
for _, repo := range repos {
|
||||||
if image.Manifest.ArtifactType == imageUtil.TestFakeSignatureArtType && image.Manifest.Subject != nil {
|
if _, found := repoNames[repo.Name]; found {
|
||||||
signedManifestDig := image.Manifest.Subject.Digest.String()
|
return fmt.Errorf("%w '%s'", zerr.ErrMultipleReposSameName, repo.Name)
|
||||||
repoMeta.Signatures[signedManifestDig] = mTypes.ManifestSignatures{
|
|
||||||
"fakeSignature": []mTypes.SignatureInfo{{SignatureManifestDigest: image.ManifestDescriptor.Digest.String()}},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
repoMeta.Statistics[image.DigestStr()] = image.Statistics
|
repoNames[repo.Name] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
manifestMetadataMap[image.DigestStr()] = mTypes.ManifestMetadata{
|
return nil
|
||||||
ManifestBlob: image.ManifestDescriptor.Data,
|
}
|
||||||
ConfigBlob: image.ConfigDescriptor.Data,
|
|
||||||
DownloadCount: image.Statistics.DownloadCount,
|
func GetFakeSignatureInfo(signatureDigest string) map[string][]mTypes.SignatureInfo {
|
||||||
|
return map[string][]mTypes.SignatureInfo{
|
||||||
|
"fake-signature": {
|
||||||
|
{
|
||||||
|
SignatureManifestDigest: signatureDigest,
|
||||||
|
LayersInfo: []mTypes.LayerInfo{},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,8 +41,8 @@ function setup() {
|
|||||||
"region": "us-east-2",
|
"region": "us-east-2",
|
||||||
"cacheTablename": "BlobTable",
|
"cacheTablename": "BlobTable",
|
||||||
"repoMetaTablename": "RepoMetadataTable",
|
"repoMetaTablename": "RepoMetadataTable",
|
||||||
"manifestDataTablename": "ManifestDataTable",
|
"imageMetaTablename": "ImageMetaTable",
|
||||||
"indexDataTablename": "IndexDataTable",
|
"repoBlobsInfoTablename": "RepoBlobsInfoTable",
|
||||||
"userDataTablename": "UserDataTable",
|
"userDataTablename": "UserDataTable",
|
||||||
"apiKeyTablename":"ApiKeyTable",
|
"apiKeyTablename":"ApiKeyTable",
|
||||||
"versionTablename": "Version"
|
"versionTablename": "Version"
|
||||||
|
Loading…
Reference in New Issue
Block a user