0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2025-02-17 23:45:36 -05:00
zot/pkg/meta/redis/redis_test.go
Andrei Aaron 05823cd74f
redis driver for blob cache information and metadb (#2865)
* feat: add redis cache support

https://github.com/project-zot/zot/pull/2005
Fixes https://github.com/project-zot/zot/issues/2004

* feat: add redis cache support

Currently, we have dynamoDB as the remote shared cache but ideal only
for the cloud use case.
For on-prem use case, add support for redis.

Signed-off-by: Ramkumar Chinchani <rchincha@cisco.com>

* feat(redis): added blackbox tests for redis

Signed-off-by: Petu Eusebiu <peusebiu@cisco.com>

* feat(redis): dummy implementation of MetaDB interface for redis cache

Signed-off-by: Alexei Dodon <adodon@cisco.com>

* feat: check validity of driver configuration on metadb instantiation

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

* feat: multiple fixes for redis cache driver implementation

- add missing method GetAllBlobs
- add redis cache tests, with and without mocking

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

* feat(redis): redis implementation for MetaDB

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

* feat(redis): use redsync to block concurrent write access to the redis DB

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

* feat(redis): update .github/workflows/cluster.yaml to also test redis

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

* feat(metadb): add keyPrefix parameter for redis and remove unneeded method meta.Crate()

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

* feat(redis): support RedisCluster configuration and add unit tests

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

* feat(redis): more tests for redis metadb implementation

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

* feat(redis): add more examples and update examples/README.md

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

* feat(redis): move option parsing and redis client initialization under pkg/api/config/redis

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

* chore(cachedb): move Cache interface to pkg/storage/types

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

* feat(redis): reorganize code in pkg/storage/cache.go

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

* feat(redis): call redis.SetLogger() with the zot logger as parameter

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

* feat(redis): rename pkg/meta/redisdb to pkg/meta/redis

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

---------

Signed-off-by: Ramkumar Chinchani <rchincha@cisco.com>
Signed-off-by: Petu Eusebiu <peusebiu@cisco.com>
Signed-off-by: Alexei Dodon <adodon@cisco.com>
Signed-off-by: Andrei Aaron <aaaron@luxoft.com>
Co-authored-by: a <a@tuxpa.in>
Co-authored-by: Ramkumar Chinchani <rchincha@cisco.com>
Co-authored-by: Petu Eusebiu <peusebiu@cisco.com>
Co-authored-by: Alexei Dodon <adodon@cisco.com>
2025-01-30 11:00:52 -08:00

1532 lines
42 KiB
Go

package redis_test
import (
"context"
"errors"
"fmt"
"strings"
"testing"
"time"
"github.com/alicebob/miniredis/v2"
"github.com/go-redis/redismock/v9"
godigest "github.com/opencontainers/go-digest"
ispec "github.com/opencontainers/image-spec/specs-go/v1"
goredis "github.com/redis/go-redis/v9"
. "github.com/smartystreets/goconvey/convey"
"google.golang.org/protobuf/proto"
"zotregistry.dev/zot/pkg/log"
proto_go "zotregistry.dev/zot/pkg/meta/proto/gen"
"zotregistry.dev/zot/pkg/meta/redis"
mTypes "zotregistry.dev/zot/pkg/meta/types"
reqCtx "zotregistry.dev/zot/pkg/requestcontext"
test "zotregistry.dev/zot/pkg/test/common"
. "zotregistry.dev/zot/pkg/test/image-utils"
)
const keyPrefix = "zot"
var ErrTestError = errors.New("TestError")
type imgTrustStore struct{}
func (its imgTrustStore) VerifySignature(
signatureType string, rawSignature []byte, sigKey string, manifestDigest godigest.Digest, imageMeta mTypes.ImageMeta,
repo string,
) (mTypes.Author, mTypes.ExpiryDate, mTypes.Validity, error) {
return "", time.Time{}, false, nil
}
func TestRedisMocked(t *testing.T) {
Convey("Test redis metadb implementation", t, func() {
log := log.NewLogger("debug", "")
So(log, ShouldNotBeNil)
client, mock := redismock.NewClientMock()
defer DumpKeys(t, client) // Troubleshoot test failures
mock.ExpectPing().SetVal("PONG")
params := redis.DBDriverParameters{KeyPrefix: "zot"}
metaDB, err := redis.New(client, params, log)
So(err, ShouldBeNil)
Convey("GetAllRepoNames HGetAll error", func() {
mock.ExpectHGetAll(metaDB.RepoMetaKey).
SetErr(ErrTestError)
repoNames, err := metaDB.GetAllRepoNames()
So(errors.Is(err, ErrTestError), ShouldEqual, true)
So(len(repoNames), ShouldEqual, 0)
err = mock.ExpectationsWereMet()
So(err, ShouldBeNil)
})
Convey("GetAllRepoNames HGetAll succeeds", func() {
mock.ExpectHGetAll(metaDB.RepoMetaKey).SetVal(
map[string]string{
"repo1": "meta1",
"repo2": "meta2",
"repo3": "meta3",
},
)
repoNames, err := metaDB.GetAllRepoNames()
So(err, ShouldBeNil)
So(len(repoNames), ShouldEqual, 3)
err = mock.ExpectationsWereMet()
So(err, ShouldBeNil)
})
Convey("ResetDB Del RepoMetaKey error", func() {
mock.ExpectTxPipeline()
mock.ExpectDel(metaDB.RepoMetaKey).SetErr(ErrTestError)
err := metaDB.ResetDB()
So(err, ShouldNotBeNil)
err = mock.ExpectationsWereMet()
So(err, ShouldBeNil)
})
Convey("ResetDB Del ImageMetaKey error", func() {
mock.ExpectTxPipeline()
mock.ExpectDel(metaDB.RepoMetaKey).SetVal(0)
mock.ExpectDel(metaDB.ImageMetaKey).SetErr(ErrTestError)
err := metaDB.ResetDB()
So(err, ShouldNotBeNil)
err = mock.ExpectationsWereMet()
So(err, ShouldBeNil)
})
Convey("ResetDB Del RepoBlobsKey error", func() {
mock.ExpectTxPipeline()
mock.ExpectDel(metaDB.RepoMetaKey).SetVal(0)
mock.ExpectDel(metaDB.ImageMetaKey).SetVal(0)
mock.ExpectDel(metaDB.RepoBlobsKey).SetErr(ErrTestError)
err := metaDB.ResetDB()
So(err, ShouldNotBeNil)
err = mock.ExpectationsWereMet()
So(err, ShouldBeNil)
})
Convey("ResetDB Del RepoLastUpdatedKey error", func() {
mock.ExpectTxPipeline()
mock.ExpectDel(metaDB.RepoMetaKey).SetVal(0)
mock.ExpectDel(metaDB.ImageMetaKey).SetVal(0)
mock.ExpectDel(metaDB.RepoBlobsKey).SetVal(0)
mock.ExpectDel(metaDB.RepoLastUpdatedKey).SetErr(ErrTestError)
err := metaDB.ResetDB()
So(err, ShouldNotBeNil)
err = mock.ExpectationsWereMet()
So(err, ShouldBeNil)
})
Convey("ResetDB Del UserDataKey error", func() {
mock.ExpectTxPipeline()
mock.ExpectDel(metaDB.RepoMetaKey).SetVal(0)
mock.ExpectDel(metaDB.ImageMetaKey).SetVal(0)
mock.ExpectDel(metaDB.RepoBlobsKey).SetVal(0)
mock.ExpectDel(metaDB.RepoLastUpdatedKey).SetVal(0)
mock.ExpectDel(metaDB.UserDataKey).SetErr(ErrTestError)
err := metaDB.ResetDB()
So(err, ShouldNotBeNil)
err = mock.ExpectationsWereMet()
So(err, ShouldBeNil)
})
Convey("ResetDB Del UserAPIKeysKey error", func() {
mock.ExpectTxPipeline()
mock.ExpectDel(metaDB.RepoMetaKey).SetVal(0)
mock.ExpectDel(metaDB.ImageMetaKey).SetVal(0)
mock.ExpectDel(metaDB.RepoBlobsKey).SetVal(0)
mock.ExpectDel(metaDB.RepoLastUpdatedKey).SetVal(0)
mock.ExpectDel(metaDB.UserDataKey).SetVal(0)
mock.ExpectDel(metaDB.UserAPIKeysKey).SetErr(ErrTestError)
err := metaDB.ResetDB()
So(err, ShouldNotBeNil)
err = mock.ExpectationsWereMet()
So(err, ShouldBeNil)
})
Convey("ResetDB Del VersionKey error", func() {
mock.ExpectTxPipeline()
mock.ExpectDel(metaDB.RepoMetaKey).SetVal(0)
mock.ExpectDel(metaDB.ImageMetaKey).SetVal(0)
mock.ExpectDel(metaDB.RepoBlobsKey).SetVal(0)
mock.ExpectDel(metaDB.RepoLastUpdatedKey).SetVal(0)
mock.ExpectDel(metaDB.UserDataKey).SetVal(0)
mock.ExpectDel(metaDB.UserAPIKeysKey).SetVal(0)
mock.ExpectDel(metaDB.VersionKey).SetErr(ErrTestError)
err := metaDB.ResetDB()
So(err, ShouldNotBeNil)
err = mock.ExpectationsWereMet()
So(err, ShouldBeNil)
})
Convey("DeleteRepoMeta Del RepoMetaKey error", func() {
mock.Regexp().ExpectSetNX(metaDB.LocksKey+":Repo:repo", `.*`, 8*time.Second).
SetVal(true)
mock.ExpectTxPipeline()
mock.ExpectHDel(metaDB.RepoMetaKey, "repo").SetErr(ErrTestError)
err := metaDB.DeleteRepoMeta("repo")
So(err, ShouldNotBeNil)
err = mock.ExpectationsWereMet()
So(err, ShouldBeNil)
})
Convey("DeleteRepoMeta Del RepoBlobsKey error", func() {
mock.Regexp().ExpectSetNX(metaDB.LocksKey+":Repo:repo", `.*`, 8*time.Second).
SetVal(true)
mock.ExpectTxPipeline()
mock.ExpectHDel(metaDB.RepoMetaKey, "repo").SetVal(0)
mock.ExpectHDel(metaDB.RepoBlobsKey, "repo").SetErr(ErrTestError)
err := metaDB.DeleteRepoMeta("repo")
So(err, ShouldNotBeNil)
err = mock.ExpectationsWereMet()
So(err, ShouldBeNil)
})
Convey("DeleteRepoMeta Del RepoLastUpdatedKey error", func() {
mock.Regexp().ExpectSetNX(metaDB.LocksKey+":Repo:repo", `.*`, 8*time.Second).
SetVal(true)
mock.ExpectTxPipeline()
mock.ExpectHDel(metaDB.RepoMetaKey, "repo").SetVal(0)
mock.ExpectHDel(metaDB.RepoBlobsKey, "repo").SetVal(0)
mock.ExpectHDel(metaDB.RepoLastUpdatedKey, "repo").SetErr(ErrTestError)
err := metaDB.DeleteRepoMeta("repo")
So(err, ShouldNotBeNil)
err = mock.ExpectationsWereMet()
So(err, ShouldBeNil)
})
})
}
func TestRedisRepoMeta(t *testing.T) {
miniRedis := miniredis.RunT(t)
Convey("Test repometa implementation", t, func() {
log := log.NewLogger("debug", "")
So(log, ShouldNotBeNil)
opts, err := goredis.ParseURL("redis://" + miniRedis.Addr())
So(err, ShouldBeNil)
client := goredis.NewClient(opts)
defer DumpKeys(t, client) // Troubleshoot test failures
params := redis.DBDriverParameters{KeyPrefix: "zot"}
metaDB, err := redis.New(client, params, log)
So(err, ShouldBeNil)
Convey("Test repoMeta ops", func() {
ctx := context.Background()
// Create/Get repo meta
for i := range 5 {
repoName := fmt.Sprintf("repo%d", i+1)
digest := fmt.Sprintf("dig%d", i+1)
initialRepoMeta := mTypes.RepoMeta{
Name: repoName,
Tags: map[mTypes.Tag]mTypes.Descriptor{"tag": {Digest: digest}},
Statistics: map[mTypes.ImageDigest]mTypes.DescriptorStatistics{},
Signatures: map[mTypes.ImageDigest]mTypes.ManifestSignatures{},
Referrers: map[mTypes.ImageDigest][]mTypes.ReferrerInfo{"digest": {{Digest: digest}}},
}
err = metaDB.SetRepoMeta(repoName, initialRepoMeta)
So(err, ShouldBeNil)
expectedRepoMeta, err := metaDB.GetRepoMeta(ctx, repoName)
So(err, ShouldBeNil)
So(expectedRepoMeta.Name, ShouldEqual, initialRepoMeta.Name)
So(expectedRepoMeta.Tags["tag"].Digest, ShouldEqual, initialRepoMeta.Tags["tag"].Digest)
}
// Get Multiple, Filter and Delete repo meta
repoMetas, err := metaDB.GetMultipleRepoMeta(ctx, func(repoMeta mTypes.RepoMeta) bool {
if strings.Contains(repoMeta.Name, "repo1") || strings.Contains(repoMeta.Name, "repo4") {
return true
}
return false
})
So(err, ShouldBeNil)
So(len(repoMetas), ShouldEqual, 2)
So(repoMetas[0].Name, ShouldNotEqual, repoMetas[1].Name)
for _, repoMeta := range repoMetas {
So(repoMeta.Name, ShouldBeIn, []string{"repo1", "repo4"})
}
repoMetas, err = metaDB.FilterRepos(ctx,
func(repo string) bool {
return true
},
func(repoMeta mTypes.RepoMeta) bool {
if strings.Contains(repoMeta.Tags["tag"].Digest, "dig2") ||
strings.Contains(repoMeta.Tags["tag"].Digest, "dig5") {
return true
}
return false
},
)
So(err, ShouldBeNil)
So(len(repoMetas), ShouldEqual, 2)
So(repoMetas[0].Tags["tag"].Digest, ShouldNotEqual, repoMetas[1].Tags["tag"].Digest)
for _, repoMeta := range repoMetas {
So(repoMeta.Tags["tag"].Digest, ShouldBeIn, []string{"dig2", "dig5"})
}
repoNames, err := metaDB.GetAllRepoNames()
So(err, ShouldBeNil)
So(len(repoNames), ShouldEqual, 5)
err = metaDB.DeleteRepoMeta("repo2")
So(err, ShouldBeNil)
repoMeta, err := metaDB.GetRepoMeta(ctx, "repo2")
So(err, ShouldNotBeNil)
So(repoMeta.Name, ShouldBeEmpty)
repoNames, err = metaDB.GetAllRepoNames()
So(err, ShouldBeNil)
So(len(repoNames), ShouldEqual, 4)
repoMetas, err = metaDB.GetMultipleRepoMeta(ctx, func(repoMeta mTypes.RepoMeta) bool { return true })
So(err, ShouldBeNil)
So(len(repoMetas), ShouldEqual, 4)
repoMetas, err = metaDB.GetMultipleRepoMeta(ctx, func(repoMeta mTypes.RepoMeta) bool { return false })
So(err, ShouldBeNil)
So(len(repoMetas), ShouldEqual, 0)
repoMetas, err = metaDB.FilterRepos(ctx,
func(repo string) bool {
result := strings.Contains(repo, "repo5")
return result
},
func(repoMeta mTypes.RepoMeta) bool {
if strings.Contains(repoMeta.Tags["tag"].Digest, "dig3") ||
strings.Contains(repoMeta.Tags["tag"].Digest, "dig5") {
return true
}
return false
},
)
So(err, ShouldBeNil)
So(len(repoMetas), ShouldEqual, 1)
So(repoMetas[0].Tags["tag"].Digest, ShouldEqual, "dig5")
repoMetas, err = metaDB.SearchRepos(ctx, "repo")
So(err, ShouldBeNil)
So(len(repoMetas), ShouldEqual, 4)
repoMetas, err = metaDB.SearchRepos(ctx, "epo3")
So(err, ShouldBeNil)
So(len(repoMetas), ShouldEqual, 1)
// Stars
repoMeta, err = metaDB.GetRepoMeta(ctx, "repo1")
So(err, ShouldBeNil)
So(repoMeta, ShouldNotBeNil)
So(repoMeta.StarCount, ShouldEqual, 0)
err = metaDB.IncrementRepoStars("repo1")
So(err, ShouldBeNil)
err = metaDB.IncrementRepoStars("repo1")
So(err, ShouldBeNil)
repoMeta, err = metaDB.GetRepoMeta(ctx, "repo1")
So(err, ShouldBeNil)
So(repoMeta, ShouldNotBeNil)
So(repoMeta.StarCount, ShouldEqual, 2)
err = metaDB.DecrementRepoStars("repo1")
So(err, ShouldBeNil)
err = metaDB.DecrementRepoStars("repo1")
So(err, ShouldBeNil)
repoMeta, err = metaDB.GetRepoMeta(ctx, "repo1")
So(err, ShouldBeNil)
So(repoMeta, ShouldNotBeNil)
So(repoMeta.StarCount, ShouldEqual, 0)
err = metaDB.DecrementRepoStars("repo1")
So(err, ShouldBeNil)
repoMeta, err = metaDB.GetRepoMeta(ctx, "repo1")
So(err, ShouldBeNil)
So(repoMeta, ShouldNotBeNil)
So(repoMeta.StarCount, ShouldEqual, 0)
})
})
}
func TestRedisUnreachable(t *testing.T) {
Convey("Redis unreachable", t, func() {
miniRedis := miniredis.RunT(t)
log := log.NewLogger("debug", "")
So(log, ShouldNotBeNil)
connOpts, err := goredis.ParseURL("redis://" + miniRedis.Addr())
So(err, ShouldBeNil)
workingClient := goredis.NewClient(connOpts)
params := redis.DBDriverParameters{KeyPrefix: "zot"}
metaDB, err := redis.New(workingClient, params, log)
So(err, ShouldBeNil)
So(metaDB, ShouldNotBeNil)
connOpts, err = goredis.ParseURL("redis://127.0.0.1:" + test.GetFreePort())
So(err, ShouldBeNil)
brokenClient := goredis.NewClient(connOpts)
// Replace connection with the unreachable server
metaDB.Client = brokenClient
metaDB.SetImageTrustStore(imgTrustStore{})
userAc := reqCtx.NewUserAccessControl()
userAc.SetUsername("test")
ctx := userAc.DeriveContext(context.Background())
repo := "repo"
reference := "tag"
digest := godigest.FromString("SomeString")
image := CreateDefaultImage()
imageMeta := image.AsImageMeta()
err = metaDB.SetImageMeta(digest, imageMeta)
So(err, ShouldNotBeNil)
err = metaDB.SetRepoReference(ctx, repo, reference, imageMeta)
So(err, ShouldNotBeNil)
_, err = metaDB.SearchRepos(ctx, repo)
So(err, ShouldNotBeNil)
_, err = metaDB.SearchTags(ctx, repo+":"+reference)
So(err, ShouldNotBeNil)
_, err = metaDB.FilterTags(ctx, mTypes.AcceptAllRepoTag, mTypes.AcceptAllImageMeta)
So(err, ShouldNotBeNil)
_, err = metaDB.FilterRepos(ctx, mTypes.AcceptAllRepoNames, mTypes.AcceptAllRepoMeta)
So(err, ShouldNotBeNil)
_, err = metaDB.GetRepoMeta(ctx, repo)
So(err, ShouldNotBeNil)
_, err = metaDB.GetFullImageMeta(ctx, repo, reference)
So(err, ShouldNotBeNil)
_, err = metaDB.GetImageMeta(digest)
So(err, ShouldNotBeNil)
_, err = metaDB.GetMultipleRepoMeta(ctx, func(repoMeta mTypes.RepoMeta) bool { return true })
So(err, ShouldNotBeNil)
err = metaDB.AddManifestSignature(repo, digest, mTypes.SignatureMetadata{})
So(err, ShouldNotBeNil)
err = metaDB.DeleteSignature(repo, digest, mTypes.SignatureMetadata{})
So(err, ShouldNotBeNil)
err = metaDB.UpdateSignaturesValidity(ctx, repo, digest)
So(err, ShouldNotBeNil)
err = metaDB.IncrementRepoStars(repo)
So(err, ShouldNotBeNil)
err = metaDB.DecrementRepoStars(repo)
So(err, ShouldNotBeNil)
err = metaDB.SetRepoMeta(repo, mTypes.RepoMeta{})
So(err, ShouldNotBeNil)
err = metaDB.DeleteRepoMeta(repo)
So(err, ShouldNotBeNil)
_, err = metaDB.GetReferrersInfo(repo, digest, []string{})
So(err, ShouldNotBeNil)
err = metaDB.UpdateStatsOnDownload(repo, reference)
So(err, ShouldNotBeNil)
_, err = metaDB.FilterImageMeta(ctx, []string{digest.String()})
So(err, ShouldNotBeNil)
err = metaDB.RemoveRepoReference(repo, reference, digest)
So(err, ShouldNotBeNil)
err = metaDB.ResetRepoReferences(repo)
So(err, ShouldNotBeNil)
t := metaDB.GetRepoLastUpdated(repo)
So(t, ShouldEqual, time.Time{})
_, err = metaDB.GetAllRepoNames()
So(err, ShouldNotBeNil)
err = metaDB.ResetDB()
So(err, ShouldNotBeNil)
err = metaDB.PatchDB()
So(err, ShouldNotBeNil)
_, err = metaDB.GetStarredRepos(ctx)
So(err, ShouldNotBeNil)
_, err = metaDB.GetBookmarkedRepos(ctx)
So(err, ShouldNotBeNil)
_, err = metaDB.ToggleStarRepo(ctx, repo)
So(err, ShouldNotBeNil)
_, err = metaDB.ToggleBookmarkRepo(ctx, repo)
So(err, ShouldNotBeNil)
_, err = metaDB.GetUserData(ctx)
So(err, ShouldNotBeNil)
err = metaDB.SetUserData(ctx, mTypes.UserData{})
So(err, ShouldNotBeNil)
err = metaDB.SetUserGroups(ctx, []string{})
So(err, ShouldNotBeNil)
_, err = metaDB.GetUserGroups(ctx)
So(err, ShouldNotBeNil)
err = metaDB.DeleteUserData(ctx)
So(err, ShouldNotBeNil)
_, err = metaDB.GetUserAPIKeyInfo("hash")
So(err, ShouldNotBeNil)
_, err = metaDB.GetUserAPIKeys(ctx)
So(err, ShouldNotBeNil)
err = metaDB.AddUserAPIKey(ctx, "hash", &mTypes.APIKeyDetails{})
So(err, ShouldNotBeNil)
_, err = metaDB.IsAPIKeyExpired(ctx, "hash")
So(err, ShouldNotBeNil)
err = metaDB.UpdateUserAPIKeyLastUsed(ctx, "hash")
So(err, ShouldNotBeNil)
err = metaDB.DeleteUserAPIKey(ctx, "test")
So(err, ShouldNotBeNil)
})
}
func TestWrapperErrors(t *testing.T) {
image := CreateDefaultImage()
imageMeta := image.AsImageMeta()
multiarchImageMeta := CreateMultiarchWith().Images([]Image{image}).Build().AsImageMeta()
badProtoBlob := []byte("bad-repo-meta")
goodRepoMetaBlob, err := proto.Marshal(&proto_go.RepoMeta{Name: "repo"})
if err != nil {
t.FailNow()
}
Convey("Errors", t, func() {
miniRedis := miniredis.RunT(t)
log := log.NewLogger("debug", "")
So(log, ShouldNotBeNil)
opts, err := goredis.ParseURL("redis://" + miniRedis.Addr())
So(err, ShouldBeNil)
client := goredis.NewClient(opts)
params := redis.DBDriverParameters{KeyPrefix: keyPrefix}
metaDB, err := redis.New(client, params, log)
So(metaDB, ShouldNotBeNil)
So(err, ShouldBeNil)
metaDB.SetImageTrustStore(imgTrustStore{})
userAc := reqCtx.NewUserAccessControl()
userAc.SetUsername("test")
ctx := userAc.DeriveContext(context.Background())
Convey("RemoveRepoReference", func() {
Convey("getProtoRepoMeta errors", func() {
err := setRepoMeta("repo", badProtoBlob, client)
So(err, ShouldBeNil)
err = metaDB.RemoveRepoReference("repo", "ref", imageMeta.Digest)
So(err, ShouldNotBeNil)
})
Convey("getProtoImageMeta errors", func() {
err := metaDB.SetRepoMeta("repo", mTypes.RepoMeta{
Name: "repo",
Tags: map[mTypes.Tag]mTypes.Descriptor{
"tag": {
MediaType: ispec.MediaTypeImageManifest,
Digest: imageMeta.Digest.String(),
},
},
})
So(err, ShouldBeNil)
err = setImageMeta(imageMeta.Digest, badProtoBlob, client)
So(err, ShouldBeNil)
err = metaDB.RemoveRepoReference("repo", "ref", imageMeta.Digest)
So(err, ShouldNotBeNil)
})
Convey("unmarshalProtoRepoBlobs errors", func() {
err := metaDB.SetRepoReference(ctx, "repo", "tag", imageMeta)
So(err, ShouldBeNil)
err = setRepoBlobInfo("repo", badProtoBlob, client)
So(err, ShouldBeNil)
err = metaDB.RemoveRepoReference("repo", "ref", imageMeta.Digest)
So(err, ShouldNotBeNil)
})
})
Convey("UpdateSignaturesValidity", func() {
metaDB.SetImageTrustStore(imgTrustStore{})
digest := image.Digest()
ctx := context.Background()
Convey("image meta blob not found", func() {
err := metaDB.UpdateSignaturesValidity(ctx, "repo", digest)
So(err, ShouldBeNil)
})
Convey("image meta unmarshal fail", func() {
err := setImageMeta(digest, badProtoBlob, client)
So(err, ShouldBeNil)
err = metaDB.UpdateSignaturesValidity(ctx, "repo", digest)
So(err, ShouldNotBeNil)
})
Convey("repo meta blob not found", func() {
err := metaDB.SetImageMeta(digest, imageMeta)
So(err, ShouldBeNil)
err = metaDB.UpdateSignaturesValidity(ctx, "repo", digest)
So(err, ShouldNotBeNil)
})
Convey("repo meta unmarshal fail", func() {
err := metaDB.SetImageMeta(digest, imageMeta)
So(err, ShouldBeNil)
err = setRepoMeta("repo", badProtoBlob, client)
So(err, ShouldBeNil)
err = metaDB.UpdateSignaturesValidity(ctx, "repo", digest)
So(err, ShouldNotBeNil)
})
})
Convey("GetRepoLastUpdated", func() {
Convey("bad blob in db", func() {
err := setRepoLastUpdated("repo", []byte("bad-blob"), client)
So(err, ShouldBeNil)
lastUpdated := metaDB.GetRepoLastUpdated("repo")
So(lastUpdated, ShouldEqual, time.Time{})
})
Convey("empty blob in db", func() {
err := setRepoLastUpdated("repo", []byte(""), client)
So(err, ShouldBeNil)
lastUpdated := metaDB.GetRepoLastUpdated("repo")
So(lastUpdated, ShouldEqual, time.Time{})
})
})
Convey("UpdateStatsOnDownload", func() {
Convey("repo meta not found", func() {
err = metaDB.UpdateStatsOnDownload("repo", "ref")
So(err, ShouldNotBeNil)
})
Convey("unmarshalProtoRepoMeta error", func() {
err := setRepoMeta("repo", badProtoBlob, client)
So(err, ShouldBeNil)
err = metaDB.UpdateStatsOnDownload("repo", "ref")
So(err, ShouldNotBeNil)
})
Convey("ref is tag and tag is not found", func() {
err := metaDB.SetRepoReference(ctx, "repo", "tag", imageMeta)
So(err, ShouldBeNil)
err = metaDB.UpdateStatsOnDownload("repo", "not-found-tag")
So(err, ShouldNotBeNil)
})
Convey("digest not found in statistics", func() {
err := metaDB.SetRepoReference(ctx, "repo", "tag", imageMeta)
So(err, ShouldBeNil)
err = metaDB.UpdateStatsOnDownload("repo", godigest.FromString("not-found").String())
So(err, ShouldNotBeNil)
})
})
Convey("GetReferrersInfo", func() {
Convey("unmarshalProtoRepoMeta error", func() {
err := setRepoMeta("repo", badProtoBlob, client)
So(err, ShouldBeNil)
_, err = metaDB.GetReferrersInfo("repo", "refDig", []string{})
So(err, ShouldNotBeNil)
})
})
Convey("ResetRepoReferences", func() {
Convey("unmarshalProtoRepoMeta error", func() {
err := setRepoMeta("repo", badProtoBlob, client)
So(err, ShouldBeNil)
err = metaDB.ResetRepoReferences("repo")
So(err, ShouldNotBeNil)
})
})
Convey("DecrementRepoStars", func() {
Convey("unmarshalProtoRepoMeta error", func() {
err := setRepoMeta("repo", badProtoBlob, client)
So(err, ShouldBeNil)
err = metaDB.DecrementRepoStars("repo")
So(err, ShouldNotBeNil)
})
})
Convey("IncrementRepoStars", func() {
Convey("unmarshalProtoRepoMeta error", func() {
err := setRepoMeta("repo", badProtoBlob, client)
So(err, ShouldBeNil)
err = metaDB.IncrementRepoStars("repo")
So(err, ShouldNotBeNil)
})
})
Convey("DeleteSignature", func() {
Convey("repo meta not found", func() {
err = metaDB.DeleteSignature("repo", godigest.FromString("dig"), mTypes.SignatureMetadata{})
So(err, ShouldNotBeNil)
})
Convey("unmarshalProtoRepoMeta error", func() {
err := setRepoMeta("repo", badProtoBlob, client)
So(err, ShouldBeNil)
err = metaDB.DeleteSignature("repo", godigest.FromString("dig"), mTypes.SignatureMetadata{})
So(err, ShouldNotBeNil)
})
})
Convey("AddManifestSignature", func() {
Convey("unmarshalProtoRepoMeta error", func() {
err := setRepoMeta("repo", badProtoBlob, client)
So(err, ShouldBeNil)
err = metaDB.AddManifestSignature("repo", godigest.FromString("dig"), mTypes.SignatureMetadata{})
So(err, ShouldNotBeNil)
})
})
Convey("GetMultipleRepoMeta", func() {
Convey("unmarshalProtoRepoMeta error", func() {
err := setRepoMeta("repo", badProtoBlob, client)
So(err, ShouldBeNil)
_, err = metaDB.GetMultipleRepoMeta(ctx, func(repoMeta mTypes.RepoMeta) bool { return true })
So(err, ShouldNotBeNil)
})
})
Convey("GetImageMeta", func() {
Convey("malformed image manifest", func() {
badImageDigest := godigest.FromString("bad-image-manifest")
err = setImageMeta(badImageDigest, badProtoBlob, client)
So(err, ShouldBeNil)
_, err := metaDB.GetImageMeta(badImageDigest)
So(err, ShouldNotBeNil)
})
Convey("good image index, malformed inside manifest", func() {
goodIndexBadManifestDigest := godigest.FromString("good-index-bad-manifests")
err = metaDB.SetImageMeta(goodIndexBadManifestDigest, multiarchImageMeta)
So(err, ShouldBeNil)
err = setImageMeta(image.Digest(), badProtoBlob, client)
So(err, ShouldBeNil)
_, err := metaDB.GetImageMeta(image.Digest())
So(err, ShouldNotBeNil)
})
})
Convey("GetFullImageMeta", func() {
Convey("repo meta not found", func() {
_, err := metaDB.GetFullImageMeta(ctx, "repo", "tag")
So(err, ShouldNotBeNil)
})
Convey("unmarshalProtoRepoMeta fails", func() {
err := setRepoMeta("repo", badProtoBlob, client)
So(err, ShouldBeNil)
_, err = metaDB.GetFullImageMeta(ctx, "repo", "tag")
So(err, ShouldNotBeNil)
})
Convey("tag not found", func() {
err := setRepoMeta("repo", goodRepoMetaBlob, client)
So(err, ShouldBeNil)
_, err = metaDB.GetFullImageMeta(ctx, "repo", "tag-not-found")
So(err, ShouldNotBeNil)
})
Convey("getProtoImageMeta fails", func() {
err := metaDB.SetRepoMeta("repo", mTypes.RepoMeta{
Name: "repo",
Tags: map[mTypes.Tag]mTypes.Descriptor{
"tag": {
MediaType: ispec.MediaTypeImageManifest,
Digest: godigest.FromString("not-found").String(),
},
},
})
So(err, ShouldBeNil)
_, err = metaDB.GetFullImageMeta(ctx, "repo", "tag")
So(err, ShouldNotBeNil)
})
Convey("image is index, fail to get manifests", func() {
err := metaDB.SetImageMeta(multiarchImageMeta.Digest, multiarchImageMeta)
So(err, ShouldBeNil)
err = metaDB.SetRepoMeta("repo", mTypes.RepoMeta{
Name: "repo",
Tags: map[mTypes.Tag]mTypes.Descriptor{
"tag": {
MediaType: ispec.MediaTypeImageIndex,
Digest: multiarchImageMeta.Digest.String(),
},
},
})
So(err, ShouldBeNil)
_, err = metaDB.GetFullImageMeta(ctx, "repo", "tag")
So(err, ShouldNotBeNil)
})
})
Convey("FilterRepos", func() {
err := setRepoMeta("repo", badProtoBlob, client)
So(err, ShouldBeNil)
_, err = metaDB.FilterRepos(ctx, mTypes.AcceptAllRepoNames, mTypes.AcceptAllRepoMeta)
So(err, ShouldNotBeNil)
})
Convey("SearchTags", func() {
Convey("unmarshalProtoRepoMeta fails", func() {
err := setRepoMeta("repo", badProtoBlob, client)
So(err, ShouldBeNil)
// manifests are missing
_, err = metaDB.SearchTags(ctx, "repo:")
So(err, ShouldNotBeNil)
})
Convey("found repo meta", func() {
Convey("bad image manifest", func() {
badImageDigest := godigest.FromString("bad-image-manifest")
err := metaDB.SetRepoMeta("repo", mTypes.RepoMeta{
Name: "repo",
Tags: map[mTypes.Tag]mTypes.Descriptor{
"bad-image-manifest": {
MediaType: ispec.MediaTypeImageManifest,
Digest: badImageDigest.String(),
},
},
})
So(err, ShouldBeNil)
err = setImageMeta(badImageDigest, badProtoBlob, client)
So(err, ShouldBeNil)
_, err = metaDB.SearchTags(ctx, "repo:")
So(err, ShouldNotBeNil)
})
Convey("bad image index", func() {
badIndexDigest := godigest.FromString("bad-image-manifest")
err := metaDB.SetRepoMeta("repo", mTypes.RepoMeta{
Name: "repo",
Tags: map[mTypes.Tag]mTypes.Descriptor{
"bad-image-index": {
MediaType: ispec.MediaTypeImageIndex,
Digest: badIndexDigest.String(),
},
},
})
So(err, ShouldBeNil)
err = setImageMeta(badIndexDigest, badProtoBlob, client)
So(err, ShouldBeNil)
_, err = metaDB.SearchTags(ctx, "repo:")
So(err, ShouldNotBeNil)
})
Convey("good image index, bad inside manifest", func() {
goodIndexBadManifestDigest := godigest.FromString("good-index-bad-manifests")
err := metaDB.SetRepoMeta("repo", mTypes.RepoMeta{
Name: "repo",
Tags: map[mTypes.Tag]mTypes.Descriptor{
"good-index-bad-manifests": {
MediaType: ispec.MediaTypeImageIndex,
Digest: goodIndexBadManifestDigest.String(),
},
},
})
So(err, ShouldBeNil)
err = metaDB.SetImageMeta(goodIndexBadManifestDigest, multiarchImageMeta)
So(err, ShouldBeNil)
err = setImageMeta(image.Digest(), badProtoBlob, client)
So(err, ShouldBeNil)
_, err = metaDB.SearchTags(ctx, "repo:")
So(err, ShouldNotBeNil)
})
Convey("bad media type", func() {
err := metaDB.SetRepoMeta("repo", mTypes.RepoMeta{
Name: "repo",
Tags: map[mTypes.Tag]mTypes.Descriptor{
"mad-media-type": {
MediaType: "bad media type",
Digest: godigest.FromString("dig").String(),
},
},
})
So(err, ShouldBeNil)
_, err = metaDB.SearchTags(ctx, "repo:")
So(err, ShouldBeNil)
})
})
})
Convey("FilterTags", func() {
Convey("unmarshalProtoRepoMeta fails", func() {
err := setRepoMeta("repo", badProtoBlob, client)
So(err, ShouldBeNil)
_, err = metaDB.FilterTags(ctx, mTypes.AcceptAllRepoTag, mTypes.AcceptAllImageMeta)
So(err, ShouldNotBeNil)
})
Convey("bad media Type fails", func() {
err := metaDB.SetRepoMeta("repo", mTypes.RepoMeta{
Name: "repo",
Tags: map[mTypes.Tag]mTypes.Descriptor{
"bad-repo-meta": {
MediaType: "bad media type",
Digest: godigest.FromString("dig").String(),
},
},
})
So(err, ShouldBeNil)
_, err = metaDB.FilterTags(ctx, mTypes.AcceptAllRepoTag, mTypes.AcceptAllImageMeta)
So(err, ShouldBeNil)
})
})
Convey("SearchRepos", func() {
Convey("unmarshalProtoRepoMeta fails", func() {
err := setRepoMeta("repo", badProtoBlob, client)
So(err, ShouldBeNil)
// manifests are missing
_, err = metaDB.SearchRepos(ctx, "repo")
So(err, ShouldNotBeNil)
})
})
Convey("FilterImageMeta", func() {
Convey("MediaType ImageIndex, getProtoImageMeta fails", func() {
err := metaDB.SetImageMeta(multiarchImageMeta.Digest, multiarchImageMeta)
So(err, ShouldBeNil)
err = setImageMeta(image.Digest(), badProtoBlob, client)
So(err, ShouldBeNil)
// manifests are missing
_, err = metaDB.FilterImageMeta(ctx, []string{multiarchImageMeta.Digest.String()})
So(err, ShouldNotBeNil)
})
})
Convey("SetRepoReference", func() {
Convey("getProtoRepoMeta errors", func() {
err := setRepoMeta("repo", badProtoBlob, client)
So(err, ShouldBeNil)
err = metaDB.SetRepoReference(ctx, "repo", "tag", imageMeta)
So(err, ShouldNotBeNil)
})
Convey("unmarshalProtoRepoBlobs errors", func() {
err := setRepoMeta("repo", goodRepoMetaBlob, client)
So(err, ShouldBeNil)
err = setRepoBlobInfo("repo", badProtoBlob, client)
So(err, ShouldBeNil)
err = metaDB.SetRepoReference(ctx, "repo", "tag", imageMeta)
So(err, ShouldNotBeNil)
})
})
Convey("AddUserAPIKey", func() {
// no userid found
userAc := reqCtx.NewUserAccessControl()
ctx := userAc.DeriveContext(context.Background())
err = metaDB.AddUserAPIKey(ctx, "", &mTypes.APIKeyDetails{})
So(err, ShouldNotBeNil)
})
Convey("UpdateUserAPIKey", func() {
// no userid found
userAc := reqCtx.NewUserAccessControl()
ctx := userAc.DeriveContext(context.Background())
err = metaDB.UpdateUserAPIKeyLastUsed(ctx, "") //nolint: contextcheck
So(err, ShouldNotBeNil)
})
Convey("DeleteUserAPIKey", func() {
err = metaDB.SetUserData(ctx, mTypes.UserData{})
So(err, ShouldBeNil)
err = metaDB.AddUserAPIKey(ctx, "hashedKey", &mTypes.APIKeyDetails{})
So(err, ShouldBeNil)
Convey("userdata not found", func() {
userAc := reqCtx.NewUserAccessControl()
userAc.SetUsername("test")
ctx := userAc.DeriveContext(context.Background())
err := metaDB.DeleteUserData(ctx)
So(err, ShouldBeNil)
err = metaDB.DeleteUserAPIKey(ctx, "")
So(err, ShouldNotBeNil)
})
userAc := reqCtx.NewUserAccessControl()
ctx := userAc.DeriveContext(context.Background())
err = metaDB.DeleteUserAPIKey(ctx, "test") //nolint: contextcheck
So(err, ShouldNotBeNil)
err = deleteUserDataBucket(client)
So(err, ShouldBeNil)
err = metaDB.DeleteUserAPIKey(ctx, "") //nolint: contextcheck
So(err, ShouldNotBeNil)
})
Convey("GetUserAPIKeyInfo", func() {
err = deleteUserAPIKeysBucket(client)
So(err, ShouldBeNil)
_, err = metaDB.GetUserAPIKeyInfo("")
So(err, ShouldNotBeNil)
})
Convey("GetUserData", func() {
err = setUserData("test", []byte("dsa8"), client)
So(err, ShouldBeNil)
_, err = metaDB.GetUserData(ctx)
So(err, ShouldNotBeNil)
err = deleteUserAPIKeysBucket(client)
So(err, ShouldBeNil)
_, err = metaDB.GetUserData(ctx)
So(err, ShouldNotBeNil)
})
Convey("SetUserData", func() {
userAc := reqCtx.NewUserAccessControl()
ctx := userAc.DeriveContext(context.Background())
err = metaDB.SetUserData(ctx, mTypes.UserData{})
So(err, ShouldNotBeNil)
err = deleteUserDataBucket(client)
So(err, ShouldBeNil)
userAc = reqCtx.NewUserAccessControl()
userAc.SetUsername("test")
ctx = userAc.DeriveContext(context.Background())
err = metaDB.SetUserData(ctx, mTypes.UserData{}) //nolint: contextcheck
So(err, ShouldBeNil)
})
Convey("DeleteUserData", func() {
userAc = reqCtx.NewUserAccessControl()
ctx = userAc.DeriveContext(context.Background()) //nolint:fatcontext // test code
err = metaDB.DeleteUserData(ctx)
So(err, ShouldNotBeNil)
err = deleteUserDataBucket(client)
So(err, ShouldBeNil)
userAc = reqCtx.NewUserAccessControl()
userAc.SetUsername("test")
ctx = userAc.DeriveContext(context.Background())
err = metaDB.DeleteUserData(ctx)
So(err, ShouldNotBeNil)
})
Convey("GetUserGroups and SetUserGroups", func() {
userAc = reqCtx.NewUserAccessControl()
ctx = userAc.DeriveContext(context.Background()) //nolint:fatcontext // test code
_, err := metaDB.GetUserGroups(ctx)
So(err, ShouldNotBeNil)
err = metaDB.SetUserGroups(ctx, []string{})
So(err, ShouldNotBeNil)
})
Convey("ToggleStarRepo bad context errors", func() {
uacKey := reqCtx.GetContextKey()
ctx := context.WithValue(context.Background(), uacKey, "bad context")
_, err := metaDB.ToggleStarRepo(ctx, "repo")
So(err, ShouldNotBeNil)
})
Convey("ToggleStarRepo, no repoMeta found", func() {
userAc := reqCtx.NewUserAccessControl()
userAc.SetUsername("username")
userAc.SetGlobPatterns("read", map[string]bool{
"repo": true,
})
ctx := userAc.DeriveContext(context.Background())
err = setRepoMeta("repo", []byte("bad repo"), client)
So(err, ShouldBeNil)
_, err = metaDB.ToggleStarRepo(ctx, "repo")
So(err, ShouldNotBeNil)
})
Convey("ToggleStarRepo bad UserData found", func() {
userAc := reqCtx.NewUserAccessControl()
userAc.SetUsername("username")
userAc.SetGlobPatterns("read", map[string]bool{
"repo": true,
})
ctx := userAc.DeriveContext(context.Background())
err = setUserData("username", []byte("dsa8"), client)
So(err, ShouldBeNil)
_, err = metaDB.ToggleStarRepo(ctx, "repo")
So(err, ShouldNotBeNil)
})
Convey("ToggleStarRepo, bad repoMeta found", func() {
userAc := reqCtx.NewUserAccessControl()
userAc.SetUsername("username")
userAc.SetGlobPatterns("read", map[string]bool{
"repo": true,
})
ctx := userAc.DeriveContext(context.Background())
_, err = metaDB.ToggleStarRepo(ctx, "repo")
So(err, ShouldNotBeNil)
})
Convey("ToggleBookmarkRepo bad context errors", func() {
uacKey := reqCtx.GetContextKey()
ctx := context.WithValue(context.Background(), uacKey, "bad context")
_, err := metaDB.ToggleBookmarkRepo(ctx, "repo")
So(err, ShouldNotBeNil)
})
Convey("ToggleBookmarkRepo bad UserData found", func() {
userAc := reqCtx.NewUserAccessControl()
userAc.SetUsername("username")
userAc.SetGlobPatterns("read", map[string]bool{
"repo": true,
})
ctx := userAc.DeriveContext(context.Background())
err = setUserData("username", []byte("dsa8"), client)
So(err, ShouldBeNil)
_, err = metaDB.ToggleBookmarkRepo(ctx, "repo")
So(err, ShouldNotBeNil)
})
Convey("GetUserData bad context errors", func() {
uacKey := reqCtx.GetContextKey()
ctx := context.WithValue(context.Background(), uacKey, "bad context")
_, err := metaDB.GetUserData(ctx)
So(err, ShouldNotBeNil)
})
Convey("SetUserData bad context errors", func() {
uacKey := reqCtx.GetContextKey()
ctx := context.WithValue(context.Background(), uacKey, "bad context")
err := metaDB.SetUserData(ctx, mTypes.UserData{})
So(err, ShouldNotBeNil)
})
Convey("GetUserGroups bad context errors", func() {
_, err := metaDB.GetUserGroups(ctx)
So(err, ShouldNotBeNil)
uacKey := reqCtx.GetContextKey()
ctx := context.WithValue(context.Background(), uacKey, "bad context")
_, err = metaDB.GetUserGroups(ctx) //nolint: contextcheck
So(err, ShouldNotBeNil)
})
Convey("SetUserGroups bad context errors", func() {
uacKey := reqCtx.GetContextKey()
ctx := context.WithValue(context.Background(), uacKey, "bad context")
err := metaDB.SetUserGroups(ctx, []string{})
So(err, ShouldNotBeNil)
})
Convey("SetUserGroups bad UserData found", func() {
userAc := reqCtx.NewUserAccessControl()
userAc.SetUsername("username")
userAc.SetGlobPatterns("read", map[string]bool{
"repo": true,
})
ctx := userAc.DeriveContext(context.Background())
err = setUserData("username", []byte("dsa8"), client)
So(err, ShouldBeNil)
err = metaDB.SetUserGroups(ctx, []string{})
So(err, ShouldNotBeNil)
})
Convey("AddUserAPIKey bad context errors", func() {
uacKey := reqCtx.GetContextKey()
ctx := context.WithValue(context.Background(), uacKey, "bad context")
err := metaDB.AddUserAPIKey(ctx, "", &mTypes.APIKeyDetails{})
So(err, ShouldNotBeNil)
})
Convey("AddUserAPIKey bad UserData found", func() {
userAc := reqCtx.NewUserAccessControl()
userAc.SetUsername("username")
userAc.SetGlobPatterns("read", map[string]bool{
"repo": true,
})
ctx := userAc.DeriveContext(context.Background())
err = setUserData("username", []byte("dsa8"), client)
So(err, ShouldBeNil)
err = metaDB.AddUserAPIKey(ctx, "", &mTypes.APIKeyDetails{})
So(err, ShouldNotBeNil)
})
Convey("DeleteUserAPIKey bad context errors", func() {
uacKey := reqCtx.GetContextKey()
ctx := context.WithValue(context.Background(), uacKey, "bad context")
err := metaDB.DeleteUserAPIKey(ctx, "")
So(err, ShouldNotBeNil)
})
Convey("GetUserAPIKeys bad UserData found", func() {
userAc := reqCtx.NewUserAccessControl()
userAc.SetUsername("username")
userAc.SetGlobPatterns("read", map[string]bool{
"repo": true,
})
ctx := userAc.DeriveContext(context.Background())
err = setUserData("username", []byte("dsa8"), client)
So(err, ShouldBeNil)
_, err = metaDB.GetUserAPIKeys(ctx)
So(err, ShouldNotBeNil)
})
Convey("IsAPIKeyExpired bad UserData found", func() {
userAc := reqCtx.NewUserAccessControl()
userAc.SetUsername("username")
userAc.SetGlobPatterns("read", map[string]bool{
"repo": true,
})
ctx := userAc.DeriveContext(context.Background())
err = setUserData("username", []byte("dsa8"), client)
So(err, ShouldBeNil)
_, err = metaDB.IsAPIKeyExpired(ctx, "")
So(err, ShouldNotBeNil)
})
Convey("UpdateUserAPIKeyLastUsed bad context errors", func() {
uacKey := reqCtx.GetContextKey()
ctx := context.WithValue(context.Background(), uacKey, "bad context")
err := metaDB.UpdateUserAPIKeyLastUsed(ctx, "")
So(err, ShouldNotBeNil)
})
Convey("UpdateUserAPIKeyLastUsed bad UserData found", func() {
userAc := reqCtx.NewUserAccessControl()
userAc.SetUsername("username")
userAc.SetGlobPatterns("read", map[string]bool{
"repo": true,
})
ctx := userAc.DeriveContext(context.Background())
err = setUserData("username", []byte("dsa8"), client)
So(err, ShouldBeNil)
err = metaDB.UpdateUserAPIKeyLastUsed(ctx, "")
So(err, ShouldNotBeNil)
})
Convey("DeleteUserData bad context errors", func() {
uacKey := reqCtx.GetContextKey()
ctx := context.WithValue(context.Background(), uacKey, "bad context")
err := metaDB.DeleteUserData(ctx)
So(err, ShouldNotBeNil)
})
Convey("GetStarredRepos bad context errors", func() {
uacKey := reqCtx.GetContextKey()
ctx := context.WithValue(context.Background(), uacKey, "bad context")
_, err := metaDB.GetStarredRepos(ctx)
So(err, ShouldNotBeNil)
})
Convey("GetBookmarkedRepos bad context errors", func() {
uacKey := reqCtx.GetContextKey()
ctx := context.WithValue(context.Background(), uacKey, "bad context")
_, err := metaDB.GetBookmarkedRepos(ctx)
So(err, ShouldNotBeNil)
})
Convey("GetUserRepoMeta unmarshal error", func() {
userAc := reqCtx.NewUserAccessControl()
userAc.SetUsername("username")
userAc.SetGlobPatterns("read", map[string]bool{
"repo": true,
})
ctx := userAc.DeriveContext(context.Background())
err = setRepoMeta("repo", []byte("bad repo"), client)
So(err, ShouldBeNil)
_, err := metaDB.GetRepoMeta(ctx, "repo")
So(err, ShouldNotBeNil)
})
})
}
func setRepoMeta(repo string, blob []byte, client *goredis.Client) error { //nolint: unparam
ctx := context.Background()
key := keyPrefix + ":" + redis.RepoMetaBucket
return client.HSet(ctx, key, repo, blob).Err()
}
func setRepoLastUpdated(repo string, blob []byte, client *goredis.Client) error {
ctx := context.Background()
key := keyPrefix + ":" + redis.RepoLastUpdatedBucket
return client.HSet(ctx, key, repo, blob).Err()
}
func setImageMeta(digest godigest.Digest, blob []byte, client *goredis.Client) error {
ctx := context.Background()
key := keyPrefix + ":" + redis.ImageMetaBucket
return client.HSet(ctx, key, digest.String(), blob).Err()
}
func setRepoBlobInfo(repo string, blob []byte, client *goredis.Client) error {
ctx := context.Background()
key := keyPrefix + ":" + redis.RepoBlobsBucket
return client.HSet(ctx, key, repo, blob).Err()
}
func setUserData(userID string, blob []byte, client *goredis.Client) error {
ctx := context.Background()
key := keyPrefix + ":" + redis.UserDataBucket
return client.HSet(ctx, key, userID, blob).Err()
}
func deleteUserDataBucket(client *goredis.Client) error {
ctx := context.Background()
key := keyPrefix + ":" + redis.UserDataBucket
return client.Del(ctx, key).Err()
}
func deleteUserAPIKeysBucket(client *goredis.Client) error {
ctx := context.Background()
key := keyPrefix + ":" + redis.UserAPIKeysBucket
return client.Del(ctx, key).Err()
}
func DumpKeys(t *testing.T, client goredis.UniversalClient) {
t.Helper()
// Retrieve all keys
keys, err := client.Keys(context.Background(), "*").Result()
if err != nil {
t.Log("Error retrieving keys:", err)
return
}
// Print the keys
t.Log("Keys in Redis:")
for _, key := range keys {
keyType, err := client.Type(context.Background(), key).Result()
if err != nil {
t.Logf("Error retrieving type for key %s: %v\n", key, err)
continue
}
var value string
switch keyType {
case "string":
value, err = client.Get(context.Background(), key).Result()
case "list":
values, err := client.LRange(context.Background(), key, 0, -1).Result()
if err == nil {
value = fmt.Sprintf("%v", values)
}
case "hash":
values, err := client.HGetAll(context.Background(), key).Result()
if err == nil {
value = fmt.Sprintf("%v", values)
}
case "set":
values, err := client.SMembers(context.Background(), key).Result()
if err == nil {
value = fmt.Sprintf("%v", values)
}
case "zset":
values, err := client.ZRange(context.Background(), key, 0, -1).Result()
if err == nil {
value = fmt.Sprintf("%v", values)
}
default:
value = "Unsupported type"
}
if err != nil {
t.Logf("Error retrieving value for key %s: %v\n", key, err)
} else {
t.Logf("Key: %s, Type: %s, Value: %s\n", key, keyType, value)
}
}
}