zotregistry.dev/zot@v1.4.4-0.20240314164342-eec277e14d20/pkg/meta/dynamodb/dynamodb_test.go (about)

     1  package dynamodb_test
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/aws/aws-sdk-go-v2/aws"
    10  	"github.com/aws/aws-sdk-go-v2/config"
    11  	"github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue"
    12  	"github.com/aws/aws-sdk-go-v2/service/dynamodb"
    13  	"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
    14  	guuid "github.com/gofrs/uuid"
    15  	godigest "github.com/opencontainers/go-digest"
    16  	ispec "github.com/opencontainers/image-spec/specs-go/v1"
    17  	"github.com/rs/zerolog"
    18  	. "github.com/smartystreets/goconvey/convey"
    19  
    20  	"zotregistry.dev/zot/pkg/extensions/imagetrust"
    21  	"zotregistry.dev/zot/pkg/log"
    22  	mdynamodb "zotregistry.dev/zot/pkg/meta/dynamodb"
    23  	mTypes "zotregistry.dev/zot/pkg/meta/types"
    24  	reqCtx "zotregistry.dev/zot/pkg/requestcontext"
    25  	. "zotregistry.dev/zot/pkg/test/image-utils"
    26  	tskip "zotregistry.dev/zot/pkg/test/skip"
    27  )
    28  
    29  const badTablename = "bad tablename"
    30  
    31  func TestIterator(t *testing.T) {
    32  	tskip.SkipDynamo(t)
    33  
    34  	const region = "us-east-2"
    35  	endpoint := os.Getenv("DYNAMODBMOCK_ENDPOINT")
    36  
    37  	uuid, err := guuid.NewV4()
    38  	if err != nil {
    39  		panic(err)
    40  	}
    41  
    42  	repoMetaTablename := "RepoMetadataTable" + uuid.String()
    43  	versionTablename := "Version" + uuid.String()
    44  	imageMetaTablename := "ImageMeta" + uuid.String()
    45  	repoBlobsTablename := "RepoBlobs" + uuid.String()
    46  	userDataTablename := "UserDataTable" + uuid.String()
    47  	apiKeyTablename := "ApiKeyTable" + uuid.String()
    48  
    49  	log := log.NewLogger("debug", "")
    50  
    51  	Convey("TestIterator", t, func() {
    52  		params := mdynamodb.DBDriverParameters{
    53  			Endpoint:               endpoint,
    54  			Region:                 region,
    55  			RepoMetaTablename:      repoMetaTablename,
    56  			ImageMetaTablename:     imageMetaTablename,
    57  			RepoBlobsInfoTablename: repoBlobsTablename,
    58  			VersionTablename:       versionTablename,
    59  			APIKeyTablename:        apiKeyTablename,
    60  			UserDataTablename:      userDataTablename,
    61  		}
    62  		client, err := mdynamodb.GetDynamoClient(params)
    63  		So(err, ShouldBeNil)
    64  
    65  		dynamoWrapper, err := mdynamodb.New(client, params, log)
    66  		So(err, ShouldBeNil)
    67  
    68  		So(dynamoWrapper.ResetTable(dynamoWrapper.ImageMetaTablename), ShouldBeNil)
    69  		So(dynamoWrapper.ResetTable(dynamoWrapper.RepoMetaTablename), ShouldBeNil)
    70  
    71  		err = dynamoWrapper.SetRepoReference(context.Background(), "repo1", "tag1", CreateRandomImage().AsImageMeta())
    72  		So(err, ShouldBeNil)
    73  
    74  		err = dynamoWrapper.SetRepoReference(context.Background(), "repo2", "tag2", CreateRandomImage().AsImageMeta())
    75  		So(err, ShouldBeNil)
    76  
    77  		err = dynamoWrapper.SetRepoReference(context.Background(), "repo3", "tag3", CreateRandomImage().AsImageMeta())
    78  		So(err, ShouldBeNil)
    79  
    80  		repoMetaAttributeIterator := mdynamodb.NewBaseDynamoAttributesIterator(
    81  			dynamoWrapper.Client,
    82  			dynamoWrapper.RepoMetaTablename,
    83  			"RepoMeta",
    84  			1,
    85  			log,
    86  		)
    87  
    88  		attribute, err := repoMetaAttributeIterator.First(context.Background())
    89  		So(err, ShouldBeNil)
    90  		So(attribute, ShouldNotBeNil)
    91  
    92  		attribute, err = repoMetaAttributeIterator.Next(context.Background())
    93  		So(err, ShouldBeNil)
    94  		So(attribute, ShouldNotBeNil)
    95  
    96  		attribute, err = repoMetaAttributeIterator.Next(context.Background())
    97  		So(err, ShouldBeNil)
    98  		So(attribute, ShouldNotBeNil)
    99  
   100  		attribute, err = repoMetaAttributeIterator.Next(context.Background())
   101  		So(err, ShouldBeNil)
   102  		So(attribute, ShouldBeNil)
   103  	})
   104  }
   105  
   106  func TestIteratorErrors(t *testing.T) {
   107  	Convey("errors", t, func() {
   108  		customResolver := aws.EndpointResolverWithOptionsFunc(
   109  			func(service, region string, options ...interface{}) (aws.Endpoint, error) {
   110  				return aws.Endpoint{
   111  					PartitionID:   "aws",
   112  					URL:           "endpoint",
   113  					SigningRegion: region,
   114  				}, nil
   115  			})
   116  
   117  		cfg, err := config.LoadDefaultConfig(context.Background(), config.WithRegion("region"),
   118  			config.WithEndpointResolverWithOptions(customResolver))
   119  		So(err, ShouldBeNil)
   120  
   121  		repoMetaAttributeIterator := mdynamodb.NewBaseDynamoAttributesIterator(
   122  			dynamodb.NewFromConfig(cfg),
   123  			"RepoMetadataTable",
   124  			"RepoMeta",
   125  			1,
   126  			log.Logger{Logger: zerolog.New(os.Stdout)},
   127  		)
   128  
   129  		_, err = repoMetaAttributeIterator.First(context.Background())
   130  		So(err, ShouldNotBeNil)
   131  	})
   132  }
   133  
   134  func TestWrapperErrors(t *testing.T) {
   135  	tskip.SkipDynamo(t)
   136  
   137  	const region = "us-east-2"
   138  
   139  	endpoint := os.Getenv("DYNAMODBMOCK_ENDPOINT")
   140  
   141  	uuid, err := guuid.NewV4()
   142  	if err != nil {
   143  		panic(err)
   144  	}
   145  
   146  	repoMetaTablename := "RepoMetadataTable" + uuid.String()
   147  	versionTablename := "Version" + uuid.String()
   148  	userDataTablename := "UserDataTable" + uuid.String()
   149  	apiKeyTablename := "ApiKeyTable" + uuid.String()
   150  	wrongTableName := "WRONG Tables"
   151  	imageMetaTablename := "ImageMeta" + uuid.String()
   152  	repoBlobsTablename := "RepoBlobs" + uuid.String()
   153  
   154  	log := log.NewLogger("debug", "")
   155  	testDigest := godigest.FromString("str")
   156  	image := CreateDefaultImage()
   157  	multi := CreateMultiarchWith().Images([]Image{image}).Build()
   158  	imageMeta := image.AsImageMeta()
   159  	multiarchImageMeta := multi.AsImageMeta()
   160  
   161  	badProtoBlob := []byte("bad-repo-meta")
   162  	// goodRepoMetaBlob, err := proto.Marshal(&proto_go.RepoMeta{Name: "repo"})
   163  	// if err != nil {
   164  	// 	t.FailNow()
   165  	// }
   166  
   167  	//nolint: contextcheck
   168  	Convey("Errors", t, func() {
   169  		params := mdynamodb.DBDriverParameters{ //nolint:contextcheck
   170  			Endpoint:               endpoint,
   171  			Region:                 region,
   172  			RepoMetaTablename:      repoMetaTablename,
   173  			ImageMetaTablename:     imageMetaTablename,
   174  			RepoBlobsInfoTablename: repoBlobsTablename,
   175  			UserDataTablename:      userDataTablename,
   176  			APIKeyTablename:        apiKeyTablename,
   177  			VersionTablename:       versionTablename,
   178  		}
   179  		client, err := mdynamodb.GetDynamoClient(params) //nolint:contextcheck
   180  		So(err, ShouldBeNil)
   181  
   182  		imgTrustStore, err := imagetrust.NewAWSImageTrustStore(params.Region, params.Endpoint)
   183  		So(err, ShouldBeNil)
   184  
   185  		dynamoWrapper, err := mdynamodb.New(client, params, log) //nolint:contextcheck
   186  		So(err, ShouldBeNil)
   187  
   188  		dynamoWrapper.SetImageTrustStore(imgTrustStore)
   189  
   190  		So(dynamoWrapper.ResetTable(dynamoWrapper.RepoMetaTablename), ShouldBeNil)  //nolint:contextcheck
   191  		So(dynamoWrapper.ResetTable(dynamoWrapper.RepoBlobsTablename), ShouldBeNil) //nolint:contextcheck
   192  		So(dynamoWrapper.ResetTable(dynamoWrapper.ImageMetaTablename), ShouldBeNil) //nolint:contextcheck
   193  		So(dynamoWrapper.ResetTable(dynamoWrapper.UserDataTablename), ShouldBeNil)  //nolint:contextcheck
   194  
   195  		userAc := reqCtx.NewUserAccessControl()
   196  		userAc.SetUsername("test")
   197  		ctx := userAc.DeriveContext(context.Background())
   198  
   199  		Convey("RemoveRepoReference", func() {
   200  			Convey("getProtoRepoMeta errors", func() {
   201  				err := setRepoMeta("repo", badProtoBlob, dynamoWrapper)
   202  				So(err, ShouldBeNil)
   203  
   204  				err = dynamoWrapper.RemoveRepoReference("repo", "ref", imageMeta.Digest)
   205  				So(err, ShouldNotBeNil)
   206  			})
   207  
   208  			Convey("getProtoImageMeta errors", func() {
   209  				err := dynamoWrapper.SetRepoMeta("repo", mTypes.RepoMeta{ //nolint: contextcheck
   210  					Name: "repo",
   211  					Tags: map[mTypes.Tag]mTypes.Descriptor{
   212  						"tag": {
   213  							MediaType: ispec.MediaTypeImageManifest,
   214  							Digest:    imageMeta.Digest.String(),
   215  						},
   216  					},
   217  				})
   218  				So(err, ShouldBeNil)
   219  
   220  				err = setImageMeta(imageMeta.Digest, badProtoBlob, dynamoWrapper)
   221  				So(err, ShouldBeNil)
   222  
   223  				err = dynamoWrapper.RemoveRepoReference("repo", "ref", imageMeta.Digest)
   224  				So(err, ShouldNotBeNil)
   225  			})
   226  
   227  			Convey("unmarshalProtoRepoBlobs errors", func() {
   228  				err := dynamoWrapper.SetRepoReference(ctx, "repo", "tag", imageMeta)
   229  				So(err, ShouldBeNil)
   230  
   231  				err = setRepoBlobInfo("repo", badProtoBlob, dynamoWrapper) //nolint: contextcheck
   232  				So(err, ShouldBeNil)
   233  
   234  				err = dynamoWrapper.RemoveRepoReference("repo", "ref", imageMeta.Digest) //nolint: contextcheck
   235  				So(err, ShouldNotBeNil)
   236  			})
   237  		})
   238  		Convey("FilterImageMeta", func() {
   239  			Convey("manifest meta unmarshal error", func() {
   240  				err = setImageMeta(image.Digest(), badProtoBlob, dynamoWrapper) //nolint: contextcheck
   241  				So(err, ShouldBeNil)
   242  
   243  				_, err = dynamoWrapper.FilterImageMeta(ctx, []string{image.DigestStr()})
   244  				So(err, ShouldNotBeNil)
   245  			})
   246  			Convey("MediaType ImageIndex, getProtoImageMeta fails", func() {
   247  				err := dynamoWrapper.SetImageMeta(multiarchImageMeta.Digest, multiarchImageMeta) //nolint: contextcheck
   248  				So(err, ShouldBeNil)
   249  
   250  				err = setImageMeta(image.Digest(), badProtoBlob, dynamoWrapper) //nolint: contextcheck
   251  				So(err, ShouldBeNil)
   252  
   253  				// manifests are missing
   254  				_, err = dynamoWrapper.FilterImageMeta(ctx, []string{multiarchImageMeta.Digest.String()})
   255  				So(err, ShouldNotBeNil)
   256  			})
   257  		})
   258  		Convey("UpdateSignaturesValidity", func() {
   259  			digest := image.Digest()
   260  
   261  			Convey("image meta blob not found", func() {
   262  				err := dynamoWrapper.UpdateSignaturesValidity(ctx, "repo", digest)
   263  				So(err, ShouldNotBeNil)
   264  			})
   265  
   266  			Convey("UpdateSignaturesValidity with context done", func() {
   267  				ctx, cancel := context.WithCancel(context.Background())
   268  				cancel()
   269  
   270  				err := dynamoWrapper.UpdateSignaturesValidity(ctx, "repo", digest)
   271  				So(err, ShouldNotBeNil)
   272  			})
   273  
   274  			Convey("image meta unmarshal fail", func() {
   275  				err := setImageMeta(digest, badProtoBlob, dynamoWrapper)
   276  				So(err, ShouldBeNil)
   277  
   278  				err = dynamoWrapper.UpdateSignaturesValidity(ctx, "repo", digest)
   279  				So(err, ShouldNotBeNil)
   280  			})
   281  
   282  			Convey("repo meta blob not found", func() {
   283  				err := dynamoWrapper.SetImageMeta(digest, imageMeta)
   284  				So(err, ShouldBeNil)
   285  
   286  				err = dynamoWrapper.UpdateSignaturesValidity(ctx, "repo", digest)
   287  				So(err, ShouldNotBeNil)
   288  			})
   289  
   290  			Convey("repo meta unmarshal fail", func() {
   291  				err := dynamoWrapper.SetImageMeta(digest, imageMeta)
   292  				So(err, ShouldBeNil)
   293  
   294  				err = setRepoMeta("repo", badProtoBlob, dynamoWrapper)
   295  				So(err, ShouldBeNil)
   296  
   297  				err = dynamoWrapper.UpdateSignaturesValidity(ctx, "repo", digest)
   298  				So(err, ShouldNotBeNil)
   299  			})
   300  		})
   301  
   302  		Convey("UpdateStatsOnDownload", func() {
   303  			Convey("unmarshalProtoRepoMeta error", func() {
   304  				err := setRepoMeta("repo", badProtoBlob, dynamoWrapper)
   305  				So(err, ShouldBeNil)
   306  
   307  				err = dynamoWrapper.UpdateStatsOnDownload("repo", "ref")
   308  				So(err, ShouldNotBeNil)
   309  			})
   310  
   311  			Convey("ref is tag and tag is not found", func() {
   312  				err := dynamoWrapper.SetRepoReference(ctx, "repo", "tag", imageMeta)
   313  				So(err, ShouldBeNil)
   314  
   315  				err = dynamoWrapper.UpdateStatsOnDownload("repo", "not-found-tag") //nolint: contextcheck
   316  				So(err, ShouldNotBeNil)
   317  			})
   318  
   319  			Convey("digest not found in statistics", func() {
   320  				err := dynamoWrapper.SetRepoReference(ctx, "repo", "tag", imageMeta)
   321  				So(err, ShouldBeNil)
   322  
   323  				err = dynamoWrapper.UpdateStatsOnDownload("repo", godigest.FromString("not-found").String()) //nolint: contextcheck
   324  				So(err, ShouldNotBeNil)
   325  			})
   326  		})
   327  		Convey("GetReferrersInfo", func() {
   328  			Convey("unmarshalProtoRepoMeta error", func() {
   329  				err := setRepoMeta("repo", badProtoBlob, dynamoWrapper)
   330  				So(err, ShouldBeNil)
   331  
   332  				_, err = dynamoWrapper.GetReferrersInfo("repo", "refDig", []string{})
   333  				So(err, ShouldNotBeNil)
   334  			})
   335  		})
   336  		Convey("DecrementRepoStars", func() {
   337  			Convey("unmarshalProtoRepoMeta error", func() {
   338  				err := setRepoMeta("repo", badProtoBlob, dynamoWrapper)
   339  				So(err, ShouldBeNil)
   340  
   341  				err = dynamoWrapper.DecrementRepoStars("repo")
   342  				So(err, ShouldNotBeNil)
   343  			})
   344  		})
   345  
   346  		Convey("IncrementRepoStars", func() {
   347  			Convey("unmarshalProtoRepoMeta error", func() {
   348  				err := setRepoMeta("repo", badProtoBlob, dynamoWrapper)
   349  				So(err, ShouldBeNil)
   350  
   351  				err = dynamoWrapper.IncrementRepoStars("repo")
   352  				So(err, ShouldNotBeNil)
   353  			})
   354  		})
   355  
   356  		Convey("GetMultipleRepoMeta", func() {
   357  			Convey("repoMetaAttributeIterator.First fails", func() {
   358  				dynamoWrapper.RepoMetaTablename = badTablename
   359  				_, err := dynamoWrapper.GetMultipleRepoMeta(ctx, func(repoMeta mTypes.RepoMeta) bool { return true })
   360  				So(err, ShouldNotBeNil)
   361  			})
   362  			Convey("repo meta unmarshal fails", func() {
   363  				err := setRepoMeta("repo", badProtoBlob, dynamoWrapper) //nolint: contextcheck
   364  				So(err, ShouldBeNil)
   365  
   366  				_, err = dynamoWrapper.GetMultipleRepoMeta(ctx, func(repoMeta mTypes.RepoMeta) bool { return true })
   367  				So(err, ShouldNotBeNil)
   368  			})
   369  		})
   370  		Convey("GetImageMeta", func() {
   371  			Convey("get image meta fails", func() {
   372  				_, err := dynamoWrapper.GetImageMeta(testDigest)
   373  				So(err, ShouldNotBeNil)
   374  			})
   375  			Convey("image index, get manifest meta fails", func() {
   376  				err := dynamoWrapper.SetRepoReference(ctx, "repo", "tag", multiarchImageMeta)
   377  				So(err, ShouldBeNil)
   378  
   379  				_, err = dynamoWrapper.GetImageMeta(multiarchImageMeta.Digest) //nolint: contextcheck
   380  				So(err, ShouldNotBeNil)
   381  			})
   382  		})
   383  		Convey("GetFullImageMeta", func() {
   384  			Convey("repo meta not found", func() {
   385  				_, err := dynamoWrapper.GetFullImageMeta(ctx, "repo", "tag")
   386  				So(err, ShouldNotBeNil)
   387  			})
   388  
   389  			Convey("unmarshalProtoRepoMeta fails", func() {
   390  				err := setRepoMeta("repo", badProtoBlob, dynamoWrapper) //nolint: contextcheck
   391  				So(err, ShouldBeNil)
   392  
   393  				_, err = dynamoWrapper.GetFullImageMeta(ctx, "repo", "tag")
   394  				So(err, ShouldNotBeNil)
   395  			})
   396  
   397  			Convey("tag not found", func() {
   398  				err := dynamoWrapper.SetRepoReference(ctx, "repo", "tag", imageMeta)
   399  				So(err, ShouldBeNil)
   400  
   401  				_, err = dynamoWrapper.GetFullImageMeta(ctx, "repo", "tag-not-found")
   402  				So(err, ShouldNotBeNil)
   403  			})
   404  
   405  			Convey("getProtoImageMeta fails", func() {
   406  				err := dynamoWrapper.SetRepoMeta("repo", mTypes.RepoMeta{ //nolint: contextcheck
   407  					Name: "repo",
   408  					Tags: map[mTypes.Tag]mTypes.Descriptor{
   409  						"tag": {
   410  							MediaType: ispec.MediaTypeImageManifest,
   411  							Digest:    godigest.FromString("not-found").String(),
   412  						},
   413  					},
   414  				})
   415  				So(err, ShouldBeNil)
   416  
   417  				_, err = dynamoWrapper.GetFullImageMeta(ctx, "repo", "tag")
   418  				So(err, ShouldNotBeNil)
   419  			})
   420  
   421  			Convey("image is index, fail to get manifests", func() {
   422  				err := dynamoWrapper.SetImageMeta(multiarchImageMeta.Digest, multiarchImageMeta) //nolint: contextcheck
   423  				So(err, ShouldBeNil)
   424  
   425  				err = dynamoWrapper.SetRepoMeta("repo", mTypes.RepoMeta{ //nolint: contextcheck
   426  					Name: "repo",
   427  					Tags: map[mTypes.Tag]mTypes.Descriptor{
   428  						"tag": {
   429  							MediaType: ispec.MediaTypeImageIndex,
   430  							Digest:    multiarchImageMeta.Digest.String(),
   431  						},
   432  					},
   433  				})
   434  				So(err, ShouldBeNil)
   435  
   436  				_, err = dynamoWrapper.GetFullImageMeta(ctx, "repo", "tag")
   437  				So(err, ShouldNotBeNil)
   438  			})
   439  		})
   440  
   441  		Convey("FilterTags", func() {
   442  			Convey("repoMetaAttributeIterator.First fails", func() {
   443  				dynamoWrapper.RepoMetaTablename = badTablename
   444  
   445  				_, err = dynamoWrapper.FilterTags(ctx, mTypes.AcceptAllRepoTag, mTypes.AcceptAllImageMeta)
   446  				So(err, ShouldNotBeNil)
   447  			})
   448  			Convey("repo meta unmarshal fails", func() {
   449  				err := setRepoMeta("repo", badProtoBlob, dynamoWrapper) //nolint: contextcheck
   450  				So(err, ShouldBeNil)
   451  
   452  				_, err = dynamoWrapper.FilterTags(ctx, mTypes.AcceptAllRepoTag, mTypes.AcceptAllImageMeta)
   453  				So(err, ShouldNotBeNil)
   454  			})
   455  			Convey("found repo meta", func() {
   456  				Convey("bad image manifest", func() {
   457  					badImageDigest := godigest.FromString("bad-image-manifest")
   458  					err := dynamoWrapper.SetRepoMeta("repo", mTypes.RepoMeta{ //nolint: contextcheck
   459  						Name: "repo",
   460  						Tags: map[mTypes.Tag]mTypes.Descriptor{
   461  							"bad-image-manifest": {
   462  								MediaType: ispec.MediaTypeImageManifest,
   463  								Digest:    badImageDigest.String(),
   464  							},
   465  						},
   466  					})
   467  					So(err, ShouldBeNil)
   468  
   469  					err = setImageMeta(badImageDigest, badProtoBlob, dynamoWrapper) //nolint: contextcheck
   470  					So(err, ShouldBeNil)
   471  
   472  					_, err = dynamoWrapper.FilterTags(ctx, mTypes.AcceptAllRepoTag, mTypes.AcceptAllImageMeta)
   473  					So(err, ShouldNotBeNil)
   474  				})
   475  				Convey("bad image index", func() {
   476  					badIndexDigest := godigest.FromString("bad-image-manifest")
   477  					err := dynamoWrapper.SetRepoMeta("repo", mTypes.RepoMeta{ //nolint: contextcheck
   478  						Name: "repo",
   479  						Tags: map[mTypes.Tag]mTypes.Descriptor{
   480  							"bad-image-index": {
   481  								MediaType: ispec.MediaTypeImageIndex,
   482  								Digest:    badIndexDigest.String(),
   483  							},
   484  						},
   485  					})
   486  					So(err, ShouldBeNil)
   487  
   488  					err = setImageMeta(badIndexDigest, badProtoBlob, dynamoWrapper) //nolint: contextcheck
   489  					So(err, ShouldBeNil)
   490  
   491  					_, err = dynamoWrapper.FilterTags(ctx, mTypes.AcceptAllRepoTag, mTypes.AcceptAllImageMeta)
   492  					So(err, ShouldNotBeNil)
   493  				})
   494  				Convey("good image index, bad inside manifest", func() {
   495  					goodIndexBadManifestDigest := godigest.FromString("good-index-bad-manifests")
   496  					err := dynamoWrapper.SetRepoMeta("repo", mTypes.RepoMeta{ //nolint: contextcheck
   497  						Name: "repo",
   498  						Tags: map[mTypes.Tag]mTypes.Descriptor{
   499  							"good-index-bad-manifests": {
   500  								MediaType: ispec.MediaTypeImageIndex,
   501  								Digest:    goodIndexBadManifestDigest.String(),
   502  							},
   503  						},
   504  					})
   505  					So(err, ShouldBeNil)
   506  
   507  					err = dynamoWrapper.SetImageMeta(goodIndexBadManifestDigest, multiarchImageMeta) //nolint: contextcheck
   508  					So(err, ShouldBeNil)
   509  
   510  					err = setImageMeta(image.Digest(), badProtoBlob, dynamoWrapper) //nolint: contextcheck
   511  					So(err, ShouldBeNil)
   512  
   513  					_, err = dynamoWrapper.FilterTags(ctx, mTypes.AcceptAllRepoTag, mTypes.AcceptAllImageMeta)
   514  					So(err, ShouldNotBeNil)
   515  				})
   516  			})
   517  		})
   518  
   519  		Convey("SearchTags", func() {
   520  			Convey("getProtoRepoMeta errors", func() {
   521  				dynamoWrapper.RepoMetaTablename = badTablename
   522  
   523  				_, err := dynamoWrapper.SearchTags(ctx, "repo")
   524  				So(err, ShouldNotBeNil)
   525  			})
   526  			Convey("found repo meta", func() {
   527  				Convey("bad image manifest", func() {
   528  					badImageDigest := godigest.FromString("bad-image-manifest")
   529  					err := dynamoWrapper.SetRepoMeta("repo", mTypes.RepoMeta{ //nolint: contextcheck
   530  						Name: "repo",
   531  						Tags: map[mTypes.Tag]mTypes.Descriptor{
   532  							"bad-image-manifest": {
   533  								MediaType: ispec.MediaTypeImageManifest,
   534  								Digest:    badImageDigest.String(),
   535  							},
   536  						},
   537  					})
   538  					So(err, ShouldBeNil)
   539  
   540  					err = setImageMeta(badImageDigest, badProtoBlob, dynamoWrapper) //nolint: contextcheck
   541  					So(err, ShouldBeNil)
   542  
   543  					_, err = dynamoWrapper.SearchTags(ctx, "repo:")
   544  					So(err, ShouldNotBeNil)
   545  				})
   546  				Convey("bad image index", func() {
   547  					badIndexDigest := godigest.FromString("bad-image-manifest")
   548  					err := dynamoWrapper.SetRepoMeta("repo", mTypes.RepoMeta{ //nolint: contextcheck
   549  						Name: "repo",
   550  						Tags: map[mTypes.Tag]mTypes.Descriptor{
   551  							"bad-image-index": {
   552  								MediaType: ispec.MediaTypeImageIndex,
   553  								Digest:    badIndexDigest.String(),
   554  							},
   555  						},
   556  					})
   557  					So(err, ShouldBeNil)
   558  
   559  					err = setImageMeta(badIndexDigest, badProtoBlob, dynamoWrapper) //nolint: contextcheck
   560  					So(err, ShouldBeNil)
   561  
   562  					_, err = dynamoWrapper.SearchTags(ctx, "repo:")
   563  					So(err, ShouldNotBeNil)
   564  				})
   565  				Convey("good image index, bad inside manifest", func() {
   566  					goodIndexBadManifestDigest := godigest.FromString("good-index-bad-manifests")
   567  					err := dynamoWrapper.SetRepoMeta("repo", mTypes.RepoMeta{ //nolint: contextcheck
   568  						Name: "repo",
   569  						Tags: map[mTypes.Tag]mTypes.Descriptor{
   570  							"good-index-bad-manifests": {
   571  								MediaType: ispec.MediaTypeImageIndex,
   572  								Digest:    goodIndexBadManifestDigest.String(),
   573  							},
   574  						},
   575  					})
   576  					So(err, ShouldBeNil)
   577  
   578  					err = dynamoWrapper.SetImageMeta(goodIndexBadManifestDigest, multiarchImageMeta) //nolint: contextcheck
   579  					So(err, ShouldBeNil)
   580  
   581  					err = setImageMeta(image.Digest(), badProtoBlob, dynamoWrapper) //nolint: contextcheck
   582  					So(err, ShouldBeNil)
   583  
   584  					_, err = dynamoWrapper.SearchTags(ctx, "repo:")
   585  					So(err, ShouldNotBeNil)
   586  				})
   587  				Convey("bad media type", func() {
   588  					err := dynamoWrapper.SetRepoMeta("repo", mTypes.RepoMeta{ //nolint: contextcheck
   589  						Name: "repo",
   590  						Tags: map[mTypes.Tag]mTypes.Descriptor{
   591  							"mad-media-type": {
   592  								MediaType: "bad media type",
   593  								Digest:    godigest.FromString("dig").String(),
   594  							},
   595  						},
   596  					})
   597  					So(err, ShouldBeNil)
   598  
   599  					_, err = dynamoWrapper.SearchTags(ctx, "repo:")
   600  					So(err, ShouldBeNil)
   601  				})
   602  			})
   603  		})
   604  
   605  		Convey("SearchRepos", func() {
   606  			Convey("repoMetaAttributeIterator.First errors", func() {
   607  				dynamoWrapper.RepoMetaTablename = badTablename
   608  
   609  				_, err := dynamoWrapper.SearchRepos(ctx, "repo")
   610  				So(err, ShouldNotBeNil)
   611  			})
   612  
   613  			Convey("repo meta unmarshal errors", func() {
   614  				err := setRepoMeta("repo", badProtoBlob, dynamoWrapper) //nolint: contextcheck
   615  				So(err, ShouldBeNil)
   616  
   617  				_, err = dynamoWrapper.SearchRepos(ctx, "repo")
   618  				So(err, ShouldNotBeNil)
   619  			})
   620  		})
   621  
   622  		Convey("SetRepoReference", func() {
   623  			Convey("SetProtoImageMeta fails", func() {
   624  				dynamoWrapper.ImageMetaTablename = badTablename
   625  
   626  				err := dynamoWrapper.SetRepoReference(ctx, "repo", "tag", image.AsImageMeta())
   627  				So(err, ShouldNotBeNil)
   628  			})
   629  			Convey("getProtoRepoMeta fails", func() {
   630  				dynamoWrapper.RepoMetaTablename = badTablename
   631  
   632  				err := dynamoWrapper.SetRepoReference(ctx, "repo", "tag", image.AsImageMeta())
   633  				So(err, ShouldNotBeNil)
   634  			})
   635  			Convey("getProtoRepoBlobs fails", func() {
   636  				dynamoWrapper.RepoBlobsTablename = badTablename
   637  
   638  				err := dynamoWrapper.SetRepoReference(ctx, "repo", "tag", image.AsImageMeta())
   639  				So(err, ShouldNotBeNil)
   640  			})
   641  		})
   642  
   643  		Convey("GetProtoImageMeta", func() {
   644  			Convey("Get request fails", func() {
   645  				dynamoWrapper.ImageMetaTablename = badTablename
   646  
   647  				_, err := dynamoWrapper.GetProtoImageMeta(ctx, testDigest)
   648  				So(err, ShouldNotBeNil)
   649  			})
   650  			Convey("unmarshal fails", func() {
   651  				err := setRepoMeta("repo", badProtoBlob, dynamoWrapper) //nolint: contextcheck
   652  				So(err, ShouldBeNil)
   653  
   654  				_, err = dynamoWrapper.GetProtoImageMeta(ctx, testDigest)
   655  				So(err, ShouldNotBeNil)
   656  			})
   657  		})
   658  
   659  		Convey("SetUserData", func() {
   660  			hashKey := "id"
   661  			apiKeys := make(map[string]mTypes.APIKeyDetails)
   662  			apiKeyDetails := mTypes.APIKeyDetails{
   663  				Label:  "apiKey",
   664  				Scopes: []string{"repo"},
   665  				UUID:   hashKey,
   666  			}
   667  
   668  			apiKeys[hashKey] = apiKeyDetails
   669  
   670  			userProfileSrc := mTypes.UserData{
   671  				Groups:  []string{"group1", "group2"},
   672  				APIKeys: apiKeys,
   673  			}
   674  
   675  			err := dynamoWrapper.SetUserData(ctx, userProfileSrc)
   676  			So(err, ShouldBeNil)
   677  
   678  			userAc := reqCtx.NewUserAccessControl()
   679  			ctx := userAc.DeriveContext(context.Background())
   680  
   681  			err = dynamoWrapper.SetUserData(ctx, mTypes.UserData{}) //nolint: contextcheck
   682  			So(err, ShouldNotBeNil)
   683  		})
   684  
   685  		Convey("DeleteUserData", func() {
   686  			err := dynamoWrapper.DeleteUserData(ctx)
   687  			So(err, ShouldBeNil)
   688  
   689  			userAc := reqCtx.NewUserAccessControl()
   690  			ctx := userAc.DeriveContext(context.Background())
   691  
   692  			err = dynamoWrapper.DeleteUserData(ctx) //nolint: contextcheck
   693  			So(err, ShouldNotBeNil)
   694  		})
   695  
   696  		Convey("ToggleBookmarkRepo no access", func() {
   697  			userAc := reqCtx.NewUserAccessControl()
   698  			userAc.SetUsername("username")
   699  			userAc.SetGlobPatterns("read", map[string]bool{
   700  				"repo": false,
   701  			})
   702  			ctx := userAc.DeriveContext(context.Background())
   703  
   704  			_, err := dynamoWrapper.ToggleBookmarkRepo(ctx, "unaccesible")
   705  			So(err, ShouldNotBeNil)
   706  		})
   707  
   708  		Convey("ToggleBookmarkRepo GetUserMeta no user data", func() {
   709  			userAc := reqCtx.NewUserAccessControl()
   710  			userAc.SetUsername("username")
   711  			userAc.SetGlobPatterns("read", map[string]bool{
   712  				"repo": true,
   713  			})
   714  			ctx := userAc.DeriveContext(context.Background())
   715  
   716  			status, err := dynamoWrapper.ToggleBookmarkRepo(ctx, "repo")
   717  			So(err, ShouldBeNil)
   718  			So(status, ShouldEqual, mTypes.Added)
   719  		})
   720  
   721  		Convey("ToggleBookmarkRepo GetUserMeta client error", func() {
   722  			userAc := reqCtx.NewUserAccessControl()
   723  			userAc.SetUsername("username")
   724  			userAc.SetGlobPatterns("read", map[string]bool{
   725  				"repo": false,
   726  			})
   727  			ctx := userAc.DeriveContext(context.Background())
   728  
   729  			dynamoWrapper.UserDataTablename = badTablename
   730  
   731  			status, err := dynamoWrapper.ToggleBookmarkRepo(ctx, "repo")
   732  			So(err, ShouldNotBeNil)
   733  			So(status, ShouldEqual, mTypes.NotChanged)
   734  		})
   735  
   736  		Convey("GetBookmarkedRepos", func() {
   737  			userAc := reqCtx.NewUserAccessControl()
   738  			userAc.SetUsername("username")
   739  			userAc.SetGlobPatterns("read", map[string]bool{
   740  				"repo": false,
   741  			})
   742  			ctx := userAc.DeriveContext(context.Background())
   743  
   744  			repos, err := dynamoWrapper.GetBookmarkedRepos(ctx)
   745  			So(err, ShouldBeNil)
   746  			So(len(repos), ShouldEqual, 0)
   747  		})
   748  
   749  		Convey("ToggleStarRepo GetUserMeta bad context", func() {
   750  			uacKey := reqCtx.GetContextKey()
   751  			ctx := context.WithValue(context.Background(), uacKey, "bad context")
   752  
   753  			_, err := dynamoWrapper.ToggleStarRepo(ctx, "repo")
   754  			So(err, ShouldNotBeNil)
   755  		})
   756  
   757  		Convey("ToggleStarRepo GetUserMeta no access", func() {
   758  			userAc := reqCtx.NewUserAccessControl()
   759  			userAc.SetUsername("username")
   760  			userAc.SetGlobPatterns("read", map[string]bool{
   761  				"repo": false,
   762  			})
   763  			ctx := userAc.DeriveContext(context.Background())
   764  
   765  			_, err := dynamoWrapper.ToggleStarRepo(ctx, "unaccesible")
   766  			So(err, ShouldNotBeNil)
   767  		})
   768  
   769  		Convey("ToggleStarRepo GetUserMeta error", func() {
   770  			userAc := reqCtx.NewUserAccessControl()
   771  			userAc.SetUsername("username")
   772  			userAc.SetGlobPatterns("read", map[string]bool{
   773  				"repo": false,
   774  			})
   775  			ctx := userAc.DeriveContext(context.Background())
   776  
   777  			dynamoWrapper.UserDataTablename = badTablename
   778  
   779  			_, err := dynamoWrapper.ToggleStarRepo(ctx, "repo")
   780  			So(err, ShouldNotBeNil)
   781  		})
   782  
   783  		Convey("ToggleStarRepo GetRepoMeta error", func() {
   784  			userAc := reqCtx.NewUserAccessControl()
   785  			userAc.SetUsername("username")
   786  			userAc.SetGlobPatterns("read", map[string]bool{
   787  				"repo": true,
   788  			})
   789  			ctx := userAc.DeriveContext(context.Background())
   790  
   791  			dynamoWrapper.RepoMetaTablename = badTablename
   792  
   793  			_, err := dynamoWrapper.ToggleStarRepo(ctx, "repo")
   794  			So(err, ShouldNotBeNil)
   795  		})
   796  
   797  		Convey("GetUserData bad context", func() {
   798  			uacKey := reqCtx.GetContextKey()
   799  			ctx := context.WithValue(context.Background(), uacKey, "bad context")
   800  
   801  			userData, err := dynamoWrapper.GetUserData(ctx)
   802  			So(err, ShouldNotBeNil)
   803  			So(userData.BookmarkedRepos, ShouldBeEmpty)
   804  			So(userData.StarredRepos, ShouldBeEmpty)
   805  		})
   806  
   807  		Convey("GetUserData client error", func() {
   808  			userAc := reqCtx.NewUserAccessControl()
   809  			userAc.SetUsername("username")
   810  			userAc.SetGlobPatterns("read", map[string]bool{
   811  				"repo": true,
   812  			})
   813  			ctx := userAc.DeriveContext(context.Background())
   814  
   815  			dynamoWrapper.UserDataTablename = badTablename
   816  
   817  			_, err := dynamoWrapper.GetUserData(ctx)
   818  			So(err, ShouldNotBeNil)
   819  		})
   820  
   821  		Convey("GetUserMeta unmarshal error, bad user data", func() {
   822  			userAc := reqCtx.NewUserAccessControl()
   823  			userAc.SetUsername("username")
   824  			userAc.SetGlobPatterns("read", map[string]bool{
   825  				"repo": true,
   826  			})
   827  			ctx := userAc.DeriveContext(context.Background())
   828  
   829  			err := setBadUserData(dynamoWrapper.Client, userDataTablename, userAc.GetUsername())
   830  			So(err, ShouldBeNil)
   831  
   832  			_, err = dynamoWrapper.GetUserData(ctx)
   833  			So(err, ShouldNotBeNil)
   834  		})
   835  
   836  		Convey("SetUserData bad context", func() {
   837  			uacKey := reqCtx.GetContextKey()
   838  			ctx := context.WithValue(context.Background(), uacKey, "bad context")
   839  
   840  			err := dynamoWrapper.SetUserData(ctx, mTypes.UserData{})
   841  			So(err, ShouldNotBeNil)
   842  		})
   843  
   844  		Convey("GetUserData bad context errors", func() {
   845  			uacKey := reqCtx.GetContextKey()
   846  			ctx := context.WithValue(context.Background(), uacKey, "bad context")
   847  
   848  			_, err := dynamoWrapper.GetUserData(ctx)
   849  			So(err, ShouldNotBeNil)
   850  		})
   851  
   852  		Convey("SetUserData bad context errors", func() {
   853  			uacKey := reqCtx.GetContextKey()
   854  			ctx := context.WithValue(context.Background(), uacKey, "bad context")
   855  
   856  			err := dynamoWrapper.SetUserData(ctx, mTypes.UserData{})
   857  			So(err, ShouldNotBeNil)
   858  		})
   859  
   860  		Convey("AddUserAPIKey bad context errors", func() {
   861  			uacKey := reqCtx.GetContextKey()
   862  			ctx := context.WithValue(context.Background(), uacKey, "bad context")
   863  
   864  			err := dynamoWrapper.AddUserAPIKey(ctx, "", &mTypes.APIKeyDetails{})
   865  			So(err, ShouldNotBeNil)
   866  		})
   867  
   868  		Convey("DeleteUserAPIKey bad context errors", func() {
   869  			uacKey := reqCtx.GetContextKey()
   870  			ctx := context.WithValue(context.Background(), uacKey, "bad context")
   871  
   872  			err := dynamoWrapper.DeleteUserAPIKey(ctx, "")
   873  			So(err, ShouldNotBeNil)
   874  		})
   875  
   876  		Convey("UpdateUserAPIKeyLastUsed bad context errors", func() {
   877  			uacKey := reqCtx.GetContextKey()
   878  			ctx := context.WithValue(context.Background(), uacKey, "bad context")
   879  
   880  			err := dynamoWrapper.UpdateUserAPIKeyLastUsed(ctx, "")
   881  			So(err, ShouldNotBeNil)
   882  		})
   883  
   884  		Convey("DeleteUserData bad context errors", func() {
   885  			uacKey := reqCtx.GetContextKey()
   886  			ctx := context.WithValue(context.Background(), uacKey, "bad context")
   887  
   888  			err := dynamoWrapper.DeleteUserData(ctx)
   889  			So(err, ShouldNotBeNil)
   890  		})
   891  
   892  		Convey("GetRepoLastUpdated", func() {
   893  			Convey("bad table", func() {
   894  				dynamoWrapper.RepoBlobsTablename = "bad-table"
   895  
   896  				lastUpdated := dynamoWrapper.GetRepoLastUpdated("repo")
   897  				So(lastUpdated, ShouldEqual, time.Time{})
   898  			})
   899  
   900  			Convey("unmarshal error", func() {
   901  				err := setRepoLastUpdated("repo", []byte("bad-blob"), dynamoWrapper)
   902  				So(err, ShouldBeNil)
   903  				lastUpdated := dynamoWrapper.GetRepoLastUpdated("repo")
   904  				So(lastUpdated, ShouldEqual, time.Time{})
   905  			})
   906  		})
   907  
   908  		Convey("DeleteUserAPIKey returns nil", func() {
   909  			userAc := reqCtx.NewUserAccessControl()
   910  			userAc.SetUsername("email")
   911  			ctx := userAc.DeriveContext(context.Background())
   912  
   913  			apiKeyDetails := make(map[string]mTypes.APIKeyDetails)
   914  			apiKeyDetails["id"] = mTypes.APIKeyDetails{
   915  				UUID: "id",
   916  			}
   917  			err := dynamoWrapper.SetUserData(ctx, mTypes.UserData{
   918  				APIKeys: apiKeyDetails,
   919  			})
   920  			So(err, ShouldBeNil)
   921  
   922  			dynamoWrapper.APIKeyTablename = wrongTableName
   923  			err = dynamoWrapper.DeleteUserAPIKey(ctx, "id")
   924  			So(err, ShouldNotBeNil)
   925  		})
   926  
   927  		Convey("AddUserAPIKey", func() {
   928  			Convey("no userid found", func() {
   929  				userAc := reqCtx.NewUserAccessControl()
   930  				ctx := userAc.DeriveContext(context.Background())
   931  
   932  				err = dynamoWrapper.AddUserAPIKey(ctx, "key", &mTypes.APIKeyDetails{})
   933  				So(err, ShouldNotBeNil)
   934  			})
   935  
   936  			userAc := reqCtx.NewUserAccessControl()
   937  			userAc.SetUsername("email")
   938  			ctx := userAc.DeriveContext(context.Background())
   939  
   940  			err := dynamoWrapper.AddUserAPIKey(ctx, "key", &mTypes.APIKeyDetails{})
   941  			So(err, ShouldBeNil)
   942  
   943  			dynamoWrapper.APIKeyTablename = wrongTableName
   944  			err = dynamoWrapper.AddUserAPIKey(ctx, "key", &mTypes.APIKeyDetails{})
   945  			So(err, ShouldNotBeNil)
   946  		})
   947  
   948  		Convey("GetUserAPIKeyInfo", func() {
   949  			dynamoWrapper.APIKeyTablename = wrongTableName
   950  			_, err := dynamoWrapper.GetUserAPIKeyInfo("key")
   951  			So(err, ShouldNotBeNil)
   952  		})
   953  
   954  		Convey("GetUserData", func() {
   955  			userAc := reqCtx.NewUserAccessControl()
   956  			ctx := userAc.DeriveContext(context.Background())
   957  
   958  			_, err := dynamoWrapper.GetUserData(ctx)
   959  			So(err, ShouldNotBeNil)
   960  
   961  			userAc = reqCtx.NewUserAccessControl()
   962  			userAc.SetUsername("email")
   963  			ctx = userAc.DeriveContext(context.Background())
   964  
   965  			dynamoWrapper.UserDataTablename = wrongTableName
   966  			_, err = dynamoWrapper.GetUserData(ctx)
   967  			So(err, ShouldNotBeNil)
   968  		})
   969  
   970  		Convey("PatchDB dwr.getDBVersion errors", func() {
   971  			dynamoWrapper.VersionTablename = badTablename
   972  
   973  			err := dynamoWrapper.PatchDB()
   974  			So(err, ShouldNotBeNil)
   975  		})
   976  
   977  		Convey("PatchDB patchIndex < version.GetVersionIndex", func() {
   978  			err := setVersion(dynamoWrapper.Client, versionTablename, "V2")
   979  			So(err, ShouldBeNil)
   980  
   981  			dynamoWrapper.Patches = []func(client *dynamodb.Client, tableNames map[string]string) error{
   982  				func(client *dynamodb.Client, tableNames map[string]string) error { return nil },
   983  				func(client *dynamodb.Client, tableNames map[string]string) error { return nil },
   984  				func(client *dynamodb.Client, tableNames map[string]string) error { return nil },
   985  			}
   986  
   987  			err = dynamoWrapper.PatchDB()
   988  			So(err, ShouldBeNil)
   989  		})
   990  
   991  		Convey("ResetRepoMetaTable client errors", func() {
   992  			dynamoWrapper.RepoMetaTablename = badTablename
   993  
   994  			err := dynamoWrapper.ResetTable(dynamoWrapper.RepoMetaTablename)
   995  			So(err, ShouldNotBeNil)
   996  		})
   997  
   998  		Convey("getDBVersion client errors", func() {
   999  			dynamoWrapper.VersionTablename = badTablename
  1000  
  1001  			err := dynamoWrapper.PatchDB()
  1002  			So(err, ShouldNotBeNil)
  1003  		})
  1004  	})
  1005  
  1006  	Convey("NewDynamoDBWrapper errors", t, func() {
  1007  		params := mdynamodb.DBDriverParameters{ //nolint:contextcheck
  1008  			Endpoint:               endpoint,
  1009  			Region:                 region,
  1010  			RepoMetaTablename:      "",
  1011  			ImageMetaTablename:     imageMetaTablename,
  1012  			RepoBlobsInfoTablename: repoBlobsTablename,
  1013  			UserDataTablename:      userDataTablename,
  1014  			APIKeyTablename:        apiKeyTablename,
  1015  			VersionTablename:       versionTablename,
  1016  		}
  1017  		client, err := mdynamodb.GetDynamoClient(params)
  1018  		So(err, ShouldBeNil)
  1019  
  1020  		_, err = mdynamodb.New(client, params, log)
  1021  		So(err, ShouldNotBeNil)
  1022  
  1023  		params = mdynamodb.DBDriverParameters{ //nolint:contextcheck
  1024  			Endpoint:               endpoint,
  1025  			Region:                 region,
  1026  			RepoMetaTablename:      repoMetaTablename,
  1027  			ImageMetaTablename:     "",
  1028  			RepoBlobsInfoTablename: repoBlobsTablename,
  1029  			UserDataTablename:      userDataTablename,
  1030  			APIKeyTablename:        apiKeyTablename,
  1031  			VersionTablename:       versionTablename,
  1032  		}
  1033  		client, err = mdynamodb.GetDynamoClient(params)
  1034  		So(err, ShouldBeNil)
  1035  
  1036  		_, err = mdynamodb.New(client, params, log)
  1037  		So(err, ShouldNotBeNil)
  1038  
  1039  		params = mdynamodb.DBDriverParameters{ //nolint:contextcheck
  1040  			Endpoint:               endpoint,
  1041  			Region:                 region,
  1042  			RepoMetaTablename:      repoMetaTablename,
  1043  			ImageMetaTablename:     imageMetaTablename,
  1044  			RepoBlobsInfoTablename: "",
  1045  			UserDataTablename:      userDataTablename,
  1046  			APIKeyTablename:        apiKeyTablename,
  1047  			VersionTablename:       versionTablename,
  1048  		}
  1049  		client, err = mdynamodb.GetDynamoClient(params)
  1050  		So(err, ShouldBeNil)
  1051  
  1052  		_, err = mdynamodb.New(client, params, log)
  1053  		So(err, ShouldNotBeNil)
  1054  
  1055  		params = mdynamodb.DBDriverParameters{ //nolint:contextcheck
  1056  			Endpoint:               endpoint,
  1057  			Region:                 region,
  1058  			RepoMetaTablename:      repoMetaTablename,
  1059  			ImageMetaTablename:     imageMetaTablename,
  1060  			RepoBlobsInfoTablename: repoBlobsTablename,
  1061  			UserDataTablename:      userDataTablename,
  1062  			APIKeyTablename:        apiKeyTablename,
  1063  			VersionTablename:       "",
  1064  		}
  1065  		client, err = mdynamodb.GetDynamoClient(params)
  1066  		So(err, ShouldBeNil)
  1067  
  1068  		_, err = mdynamodb.New(client, params, log)
  1069  		So(err, ShouldNotBeNil)
  1070  
  1071  		params = mdynamodb.DBDriverParameters{ //nolint:contextcheck
  1072  			Endpoint:               endpoint,
  1073  			Region:                 region,
  1074  			RepoMetaTablename:      repoMetaTablename,
  1075  			ImageMetaTablename:     imageMetaTablename,
  1076  			RepoBlobsInfoTablename: repoBlobsTablename,
  1077  			VersionTablename:       versionTablename,
  1078  			UserDataTablename:      "",
  1079  			APIKeyTablename:        apiKeyTablename,
  1080  		}
  1081  		client, err = mdynamodb.GetDynamoClient(params)
  1082  		So(err, ShouldBeNil)
  1083  
  1084  		_, err = mdynamodb.New(client, params, log)
  1085  		So(err, ShouldNotBeNil)
  1086  
  1087  		params = mdynamodb.DBDriverParameters{ //nolint:contextcheck
  1088  			Endpoint:               endpoint,
  1089  			Region:                 region,
  1090  			RepoMetaTablename:      repoMetaTablename,
  1091  			ImageMetaTablename:     imageMetaTablename,
  1092  			RepoBlobsInfoTablename: repoBlobsTablename,
  1093  			VersionTablename:       versionTablename,
  1094  			UserDataTablename:      userDataTablename,
  1095  			APIKeyTablename:        "",
  1096  		}
  1097  		client, err = mdynamodb.GetDynamoClient(params)
  1098  		So(err, ShouldBeNil)
  1099  
  1100  		_, err = mdynamodb.New(client, params, log)
  1101  		So(err, ShouldNotBeNil)
  1102  	})
  1103  }
  1104  
  1105  func setRepoMeta(repo string, blob []byte, dynamoWrapper *mdynamodb.DynamoDB) error { //nolint: unparam
  1106  	userAttributeValue, err := attributevalue.Marshal(blob)
  1107  	if err != nil {
  1108  		return err
  1109  	}
  1110  
  1111  	_, err = dynamoWrapper.Client.UpdateItem(context.Background(), &dynamodb.UpdateItemInput{
  1112  		ExpressionAttributeNames: map[string]string{
  1113  			"#RM": "RepoMeta",
  1114  		},
  1115  		ExpressionAttributeValues: map[string]types.AttributeValue{
  1116  			":RepoMeta": userAttributeValue,
  1117  		},
  1118  		Key: map[string]types.AttributeValue{
  1119  			"TableKey": &types.AttributeValueMemberS{
  1120  				Value: repo,
  1121  			},
  1122  		},
  1123  		TableName:        aws.String(dynamoWrapper.RepoMetaTablename),
  1124  		UpdateExpression: aws.String("SET #RM = :RepoMeta"),
  1125  	})
  1126  
  1127  	return err
  1128  }
  1129  
  1130  func setRepoLastUpdated(repo string, blob []byte, dynamoWrapper *mdynamodb.DynamoDB) error { //nolint: unparam
  1131  	lastUpdatedAttributeValue, err := attributevalue.Marshal(blob)
  1132  	if err != nil {
  1133  		return err
  1134  	}
  1135  
  1136  	_, err = dynamoWrapper.Client.UpdateItem(context.Background(), &dynamodb.UpdateItemInput{
  1137  		ExpressionAttributeNames: map[string]string{
  1138  			"#RLU": "RepoLastUpdated",
  1139  		},
  1140  		ExpressionAttributeValues: map[string]types.AttributeValue{
  1141  			":RepoLastUpdated": lastUpdatedAttributeValue,
  1142  		},
  1143  		Key: map[string]types.AttributeValue{
  1144  			"TableKey": &types.AttributeValueMemberS{
  1145  				Value: repo,
  1146  			},
  1147  		},
  1148  		TableName:        aws.String(dynamoWrapper.RepoBlobsTablename),
  1149  		UpdateExpression: aws.String("SET #RLU = :RepoLastUpdated"),
  1150  	})
  1151  
  1152  	return err
  1153  }
  1154  
  1155  func setRepoBlobInfo(repo string, blob []byte, dynamoWrapper *mdynamodb.DynamoDB) error {
  1156  	userAttributeValue, err := attributevalue.Marshal(blob)
  1157  	if err != nil {
  1158  		return err
  1159  	}
  1160  
  1161  	_, err = dynamoWrapper.Client.UpdateItem(context.Background(), &dynamodb.UpdateItemInput{
  1162  		ExpressionAttributeNames: map[string]string{
  1163  			"#RB": "RepoBlobsInfo",
  1164  		},
  1165  		ExpressionAttributeValues: map[string]types.AttributeValue{
  1166  			":RepoBlobsInfo": userAttributeValue,
  1167  		},
  1168  		Key: map[string]types.AttributeValue{
  1169  			"TableKey": &types.AttributeValueMemberS{
  1170  				Value: repo,
  1171  			},
  1172  		},
  1173  		TableName:        aws.String(dynamoWrapper.RepoBlobsTablename),
  1174  		UpdateExpression: aws.String("SET #RB = :RepoBlobsInfo"),
  1175  	})
  1176  
  1177  	return err
  1178  }
  1179  
  1180  func setImageMeta(digest godigest.Digest, blob []byte, dynamoWrapper *mdynamodb.DynamoDB) error {
  1181  	userAttributeValue, err := attributevalue.Marshal(blob)
  1182  	if err != nil {
  1183  		return err
  1184  	}
  1185  
  1186  	_, err = dynamoWrapper.Client.UpdateItem(context.Background(), &dynamodb.UpdateItemInput{
  1187  		ExpressionAttributeNames: map[string]string{
  1188  			"#IM": "ImageMeta",
  1189  		},
  1190  		ExpressionAttributeValues: map[string]types.AttributeValue{
  1191  			":ImageMeta": userAttributeValue,
  1192  		},
  1193  		Key: map[string]types.AttributeValue{
  1194  			"TableKey": &types.AttributeValueMemberS{
  1195  				Value: digest.String(),
  1196  			},
  1197  		},
  1198  		TableName:        aws.String(dynamoWrapper.ImageMetaTablename),
  1199  		UpdateExpression: aws.String("SET #IM = :ImageMeta"),
  1200  	})
  1201  
  1202  	return err
  1203  }
  1204  
  1205  func setBadUserData(client *dynamodb.Client, userDataTablename, userID string) error {
  1206  	userAttributeValue, err := attributevalue.Marshal("string")
  1207  	if err != nil {
  1208  		return err
  1209  	}
  1210  
  1211  	_, err = client.UpdateItem(context.Background(), &dynamodb.UpdateItemInput{
  1212  		ExpressionAttributeNames: map[string]string{
  1213  			"#UM": "UserData",
  1214  		},
  1215  		ExpressionAttributeValues: map[string]types.AttributeValue{
  1216  			":UserData": userAttributeValue,
  1217  		},
  1218  		Key: map[string]types.AttributeValue{
  1219  			"TableKey": &types.AttributeValueMemberS{
  1220  				Value: userID,
  1221  			},
  1222  		},
  1223  		TableName:        aws.String(userDataTablename),
  1224  		UpdateExpression: aws.String("SET #UM = :UserData"),
  1225  	})
  1226  
  1227  	return err
  1228  }
  1229  
  1230  func setVersion(client *dynamodb.Client, versionTablename string, version string) error {
  1231  	mdAttributeValue, err := attributevalue.Marshal(version)
  1232  	if err != nil {
  1233  		return err
  1234  	}
  1235  
  1236  	_, err = client.UpdateItem(context.TODO(), &dynamodb.UpdateItemInput{
  1237  		ExpressionAttributeNames: map[string]string{
  1238  			"#V": "Version",
  1239  		},
  1240  		ExpressionAttributeValues: map[string]types.AttributeValue{
  1241  			":Version": mdAttributeValue,
  1242  		},
  1243  		Key: map[string]types.AttributeValue{
  1244  			"TableKey": &types.AttributeValueMemberS{
  1245  				Value: "DBVersion",
  1246  			},
  1247  		},
  1248  		TableName:        aws.String(versionTablename),
  1249  		UpdateExpression: aws.String("SET #V = :Version"),
  1250  	})
  1251  
  1252  	return err
  1253  }