mirror of
https://github.com/project-zot/zot.git
synced 2024-12-23 22:27:35 -05:00
feb7328f50
- derivedImageList and baseImageList now use FilterTags to obtain results, each with its own filter function - images that have the exact same manifest as the one provided as a parameter are no longer considered base images or derived images - both calls can be made with specific pagination parameters, and the response will include PageInfo Signed-off-by: Alex Stan <alexandrustan96@yahoo.ro> fix(tests): fix one of the pagination tests The results were not reliable as the 2 returned tags were sorted by created date/time which was not set, resulting in an unpredictable order Signed-off-by: Andrei Aaron <andaaron@cisco.com> (cherry picked from commit be504200a1127371422aeb0e5c0219e2a1ead20a) (cherry picked from commit ed8d797e639f262a63840120afe92da7db9a7600) Signed-off-by: Andrei Aaron <aaaron@luxoft.com> Signed-off-by: Andrei Aaron <andaaron@cisco.com> Signed-off-by: Andrei Aaron <aaaron@luxoft.com> Co-authored-by: Alex Stan <alexandrustan96@yahoo.ro>
541 lines
16 KiB
Go
541 lines
16 KiB
Go
package dynamo_test
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/aws/aws-sdk-go-v2/aws"
|
|
"github.com/aws/aws-sdk-go-v2/config"
|
|
"github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue"
|
|
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
|
|
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
|
|
guuid "github.com/gofrs/uuid"
|
|
"github.com/rs/zerolog"
|
|
. "github.com/smartystreets/goconvey/convey"
|
|
|
|
"zotregistry.io/zot/pkg/log"
|
|
"zotregistry.io/zot/pkg/meta/repodb"
|
|
dynamo "zotregistry.io/zot/pkg/meta/repodb/dynamodb-wrapper"
|
|
"zotregistry.io/zot/pkg/meta/repodb/dynamodb-wrapper/iterator"
|
|
dynamoParams "zotregistry.io/zot/pkg/meta/repodb/dynamodb-wrapper/params"
|
|
)
|
|
|
|
func TestIterator(t *testing.T) {
|
|
const (
|
|
endpoint = "http://localhost:4566"
|
|
region = "us-east-2"
|
|
)
|
|
|
|
uuid, err := guuid.NewV4()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
repoMetaTablename := "RepoMetadataTable" + uuid.String()
|
|
manifestDataTablename := "ManifestDataTable" + uuid.String()
|
|
versionTablename := "Version" + uuid.String()
|
|
|
|
Convey("TestIterator", t, func() {
|
|
dynamoWrapper, err := dynamo.NewDynamoDBWrapper(dynamoParams.DBDriverParameters{
|
|
Endpoint: endpoint,
|
|
Region: region,
|
|
RepoMetaTablename: repoMetaTablename,
|
|
ManifestDataTablename: manifestDataTablename,
|
|
VersionTablename: versionTablename,
|
|
})
|
|
So(err, ShouldBeNil)
|
|
|
|
So(dynamoWrapper.ResetManifestDataTable(), ShouldBeNil)
|
|
So(dynamoWrapper.ResetRepoMetaTable(), ShouldBeNil)
|
|
|
|
err = dynamoWrapper.SetRepoTag("repo1", "tag1", "manifestType", "manifestDigest1")
|
|
So(err, ShouldBeNil)
|
|
|
|
err = dynamoWrapper.SetRepoTag("repo2", "tag2", "manifestType", "manifestDigest2")
|
|
So(err, ShouldBeNil)
|
|
|
|
err = dynamoWrapper.SetRepoTag("repo3", "tag3", "manifestType", "manifestDigest3")
|
|
So(err, ShouldBeNil)
|
|
|
|
repoMetaAttributeIterator := iterator.NewBaseDynamoAttributesIterator(
|
|
dynamoWrapper.Client,
|
|
repoMetaTablename,
|
|
"RepoMetadata",
|
|
1,
|
|
log.Logger{Logger: zerolog.New(os.Stdout)},
|
|
)
|
|
|
|
attribute, err := repoMetaAttributeIterator.First(context.Background())
|
|
So(err, ShouldBeNil)
|
|
So(attribute, ShouldNotBeNil)
|
|
|
|
attribute, err = repoMetaAttributeIterator.Next(context.Background())
|
|
So(err, ShouldBeNil)
|
|
So(attribute, ShouldNotBeNil)
|
|
|
|
attribute, err = repoMetaAttributeIterator.Next(context.Background())
|
|
So(err, ShouldBeNil)
|
|
So(attribute, ShouldNotBeNil)
|
|
|
|
attribute, err = repoMetaAttributeIterator.Next(context.Background())
|
|
So(err, ShouldBeNil)
|
|
So(attribute, ShouldBeNil)
|
|
})
|
|
}
|
|
|
|
func TestIteratorErrors(t *testing.T) {
|
|
Convey("errors", t, func() {
|
|
customResolver := aws.EndpointResolverWithOptionsFunc(
|
|
func(service, region string, options ...interface{}) (aws.Endpoint, error) {
|
|
return aws.Endpoint{
|
|
PartitionID: "aws",
|
|
URL: "endpoint",
|
|
SigningRegion: region,
|
|
}, nil
|
|
})
|
|
|
|
cfg, err := config.LoadDefaultConfig(context.Background(), config.WithRegion("region"),
|
|
config.WithEndpointResolverWithOptions(customResolver))
|
|
So(err, ShouldBeNil)
|
|
|
|
repoMetaAttributeIterator := iterator.NewBaseDynamoAttributesIterator(
|
|
dynamodb.NewFromConfig(cfg),
|
|
"RepoMetadataTable",
|
|
"RepoMetadata",
|
|
1,
|
|
log.Logger{Logger: zerolog.New(os.Stdout)},
|
|
)
|
|
|
|
_, err = repoMetaAttributeIterator.First(context.Background())
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
}
|
|
|
|
func TestWrapperErrors(t *testing.T) {
|
|
const (
|
|
endpoint = "http://localhost:4566"
|
|
region = "us-east-2"
|
|
)
|
|
|
|
uuid, err := guuid.NewV4()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
repoMetaTablename := "RepoMetadataTable" + uuid.String()
|
|
manifestDataTablename := "ManifestDataTable" + uuid.String()
|
|
versionTablename := "Version" + uuid.String()
|
|
|
|
ctx := context.Background()
|
|
|
|
Convey("Errors", t, func() {
|
|
dynamoWrapper, err := dynamo.NewDynamoDBWrapper(dynamoParams.DBDriverParameters{ //nolint:contextcheck
|
|
Endpoint: endpoint,
|
|
Region: region,
|
|
RepoMetaTablename: repoMetaTablename,
|
|
ManifestDataTablename: manifestDataTablename,
|
|
VersionTablename: versionTablename,
|
|
})
|
|
So(err, ShouldBeNil)
|
|
|
|
So(dynamoWrapper.ResetManifestDataTable(), ShouldBeNil) //nolint:contextcheck
|
|
So(dynamoWrapper.ResetRepoMetaTable(), ShouldBeNil) //nolint:contextcheck
|
|
|
|
Convey("SetManifestData", func() {
|
|
dynamoWrapper.ManifestDataTablename = "WRONG table"
|
|
|
|
err := dynamoWrapper.SetManifestData("dig", repodb.ManifestData{})
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("GetManifestData", func() {
|
|
dynamoWrapper.ManifestDataTablename = "WRONG table"
|
|
|
|
_, 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("SetManifestMeta GetRepoMeta error", func() {
|
|
err := setBadRepoMeta(dynamoWrapper.Client, repoMetaTablename, "repo1")
|
|
So(err, ShouldBeNil)
|
|
|
|
err = dynamoWrapper.SetManifestMeta("repo1", "dig", repodb.ManifestMetadata{})
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("GetManifestMeta GetManifestData not found error", func() {
|
|
err := dynamoWrapper.SetRepoTag("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", repodb.ManifestData{})
|
|
So(err, ShouldBeNil)
|
|
|
|
_, err = dynamoWrapper.GetManifestMeta("repoNotFound", "dig")
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("GetManifestMeta GetRepoMeta error", func() {
|
|
err := dynamoWrapper.SetManifestData("dig", repodb.ManifestData{})
|
|
So(err, ShouldBeNil)
|
|
|
|
err = setBadRepoMeta(dynamoWrapper.Client, repoMetaTablename, "repo")
|
|
So(err, ShouldBeNil)
|
|
|
|
_, err = dynamoWrapper.GetManifestMeta("repo", "dig")
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
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.SetRepoTag("repo", "tag", "dig", "")
|
|
So(err, ShouldBeNil)
|
|
|
|
err = dynamoWrapper.IncrementImageDownloads("repo", "notFoundTag")
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("IncrementImageDownloads GetManifestMeta error", func() {
|
|
err := dynamoWrapper.SetRepoTag("repo", "tag", "dig", "")
|
|
So(err, ShouldBeNil)
|
|
|
|
err = dynamoWrapper.IncrementImageDownloads("repo", "tag")
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("AddManifestSignature GetRepoMeta error", func() {
|
|
err := dynamoWrapper.SetRepoTag("repo", "tag", "dig", "")
|
|
So(err, ShouldBeNil)
|
|
|
|
err = dynamoWrapper.AddManifestSignature("repoNotFound", "tag", repodb.SignatureMetadata{})
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("AddManifestSignature ManifestSignatures signedManifestDigest not found error", func() {
|
|
err := dynamoWrapper.SetRepoTag("repo", "tag", "dig", "")
|
|
So(err, ShouldBeNil)
|
|
|
|
err = dynamoWrapper.AddManifestSignature("repo", "tagNotFound", repodb.SignatureMetadata{})
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("AddManifestSignature SignatureType repodb.NotationType", func() {
|
|
err := dynamoWrapper.SetRepoTag("repo", "tag", "dig", "")
|
|
So(err, ShouldBeNil)
|
|
|
|
err = dynamoWrapper.AddManifestSignature("repo", "tagNotFound", repodb.SignatureMetadata{
|
|
SignatureType: "notation",
|
|
})
|
|
So(err, ShouldBeNil)
|
|
})
|
|
|
|
Convey("DeleteSignature GetRepoMeta error", func() {
|
|
err = dynamoWrapper.DeleteSignature("repoNotFound", "tagNotFound", repodb.SignatureMetadata{})
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("DeleteSignature sigDigest.SignatureManifestDigest != sigMeta.SignatureDigest true", func() {
|
|
err := setRepoMeta(dynamoWrapper.Client, repoMetaTablename, repodb.RepoMetadata{
|
|
Name: "repo",
|
|
Signatures: map[string]repodb.ManifestSignatures{
|
|
"tag1": {
|
|
"cosign": []repodb.SignatureInfo{
|
|
{SignatureManifestDigest: "dig1"},
|
|
{SignatureManifestDigest: "dig2"},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
So(err, ShouldBeNil)
|
|
|
|
err = dynamoWrapper.DeleteSignature("repo", "tag1", repodb.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 repodb.RepoMetadata) bool { return true },
|
|
repodb.PageInput{})
|
|
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("SearchRepos repoMeta unmarshal error", func() {
|
|
err = setBadRepoMeta(dynamoWrapper.Client, repoMetaTablename, "repo") //nolint:contextcheck
|
|
So(err, ShouldBeNil)
|
|
|
|
_, _, _, err = dynamoWrapper.SearchRepos(ctx, "", repodb.Filter{}, repodb.PageInput{})
|
|
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("SearchRepos GetManifestMeta error", func() {
|
|
err := dynamoWrapper.SetRepoTag("repo", "tag1", "notFoundDigest", "") //nolint:contextcheck
|
|
So(err, ShouldBeNil)
|
|
|
|
_, _, _, err = dynamoWrapper.SearchRepos(ctx, "", repodb.Filter{}, repodb.PageInput{})
|
|
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("SearchRepos config unmarshal error", func() {
|
|
err := dynamoWrapper.SetRepoTag("repo", "tag1", "dig1", "") //nolint:contextcheck
|
|
So(err, ShouldBeNil)
|
|
|
|
err = dynamoWrapper.SetManifestData("dig1", repodb.ManifestData{ //nolint:contextcheck
|
|
ManifestBlob: []byte("{}"),
|
|
ConfigBlob: []byte("bad json"),
|
|
})
|
|
So(err, ShouldBeNil)
|
|
|
|
_, _, _, err = dynamoWrapper.SearchRepos(ctx, "", repodb.Filter{}, repodb.PageInput{})
|
|
|
|
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:", repodb.Filter{}, repodb.PageInput{})
|
|
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("SearchTags GetManifestMeta error", func() {
|
|
err := dynamoWrapper.SetRepoTag("repo", "tag1", "manifestNotFound", "") //nolint:contextcheck
|
|
So(err, ShouldBeNil)
|
|
|
|
_, _, _, err = dynamoWrapper.SearchTags(ctx, "repo:", repodb.Filter{}, repodb.PageInput{})
|
|
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("SearchTags config unmarshal error", func() {
|
|
err := dynamoWrapper.SetRepoTag("repo", "tag1", "dig1", "") //nolint:contextcheck
|
|
So(err, ShouldBeNil)
|
|
|
|
err = dynamoWrapper.SetManifestData( //nolint:contextcheck
|
|
"dig1",
|
|
repodb.ManifestData{
|
|
ManifestBlob: []byte("{}"),
|
|
ConfigBlob: []byte("bad json"),
|
|
},
|
|
)
|
|
So(err, ShouldBeNil)
|
|
|
|
_, _, _, err = dynamoWrapper.SearchTags(ctx, "repo:", repodb.Filter{}, repodb.PageInput{})
|
|
|
|
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 repodb.RepoMetadata, manifestMeta repodb.ManifestMetadata) bool {
|
|
return true
|
|
},
|
|
repodb.PageInput{},
|
|
)
|
|
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("FilterTags manifestMeta not found", func() {
|
|
err := dynamoWrapper.SetRepoTag("repo", "tag1", "manifestNotFound", "") //nolint:contextcheck
|
|
So(err, ShouldBeNil)
|
|
|
|
_, _, _, err = dynamoWrapper.FilterTags(
|
|
ctx,
|
|
func(repoMeta repodb.RepoMetadata, manifestMeta repodb.ManifestMetadata) bool {
|
|
return true
|
|
},
|
|
repodb.PageInput{},
|
|
)
|
|
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("FilterTags manifestMeta unmarshal error", func() {
|
|
err := dynamoWrapper.SetRepoTag("repo", "tag1", "dig", "") //nolint:contextcheck
|
|
So(err, ShouldBeNil)
|
|
|
|
err = setBadManifestData(dynamoWrapper.Client, manifestDataTablename, "dig") //nolint:contextcheck
|
|
So(err, ShouldBeNil)
|
|
|
|
_, _, _, err = dynamoWrapper.FilterTags(
|
|
ctx,
|
|
func(repoMeta repodb.RepoMetadata, manifestMeta repodb.ManifestMetadata) bool {
|
|
return true
|
|
},
|
|
repodb.PageInput{},
|
|
)
|
|
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("FilterTags config unmarshal error", func() {
|
|
err := dynamoWrapper.SetRepoTag("repo", "tag1", "dig1", "") //nolint:contextcheck
|
|
So(err, ShouldBeNil)
|
|
|
|
err = dynamoWrapper.SetManifestData("dig1", repodb.ManifestData{ //nolint:contextcheck
|
|
ManifestBlob: []byte("{}"),
|
|
ConfigBlob: []byte("bad json"),
|
|
})
|
|
So(err, ShouldBeNil)
|
|
|
|
_, _, _, err = dynamoWrapper.FilterTags(
|
|
ctx,
|
|
func(repoMeta repodb.RepoMetadata, manifestMeta repodb.ManifestMetadata) bool {
|
|
return true
|
|
},
|
|
repodb.PageInput{},
|
|
)
|
|
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
})
|
|
}
|
|
|
|
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 setRepoMeta(client *dynamodb.Client, repoMetadataTableName string, repoMeta repodb.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
|
|
}
|