From bea0eabcaa8c8af7a4df52a043998336c49a08d3 Mon Sep 17 00:00:00 2001 From: Laurentiu Niculae Date: Wed, 11 Jan 2023 15:08:59 +0200 Subject: [PATCH] fix(repodb): make table reset syncronous for consistent testing Signed-off-by: Laurentiu Niculae --- errors/errors.go | 1 + go.mod | 2 +- .../repodb/dynamodb-wrapper/dynamo_wrapper.go | 108 ++++++++++++++++-- 3 files changed, 98 insertions(+), 13 deletions(-) diff --git a/errors/errors.go b/errors/errors.go index fcab3604..faf56d12 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -76,4 +76,5 @@ var ( ErrLimitIsNegative = errors.New("pageturner: limit has negative value") ErrOffsetIsNegative = errors.New("pageturner: offset has negative value") ErrSortCriteriaNotSupported = errors.New("pageturner: the sort criteria is not supported") + ErrTimeout = errors.New("operation timeout") ) diff --git a/go.mod b/go.mod index 024851c1..c8529ad9 100644 --- a/go.mod +++ b/go.mod @@ -122,7 +122,7 @@ require ( github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492 // indirect github.com/aquasecurity/tfsec v0.58.11 // indirect github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect - github.com/aws/aws-sdk-go v1.44.114 // indirect + github.com/aws/aws-sdk-go v1.44.114 github.com/aws/aws-sdk-go-v2 v1.17.3 github.com/aws/aws-sdk-go-v2/config v1.18.8 github.com/aws/aws-sdk-go-v2/credentials v1.13.8 // indirect diff --git a/pkg/meta/repodb/dynamodb-wrapper/dynamo_wrapper.go b/pkg/meta/repodb/dynamodb-wrapper/dynamo_wrapper.go index f529c4eb..31eb3bd4 100644 --- a/pkg/meta/repodb/dynamodb-wrapper/dynamo_wrapper.go +++ b/pkg/meta/repodb/dynamodb-wrapper/dynamo_wrapper.go @@ -833,11 +833,11 @@ func (dwr DBWrapper) createRepoMetaTable() error { BillingMode: types.BillingModePayPerRequest, }) - if err != nil && strings.Contains(err.Error(), "Table already exists") { - return nil + if err != nil && !strings.Contains(err.Error(), "Table already exists") { + return err } - return err + return dwr.waitTableToBeCreated(dwr.RepoMetaTablename) } func (dwr DBWrapper) deleteRepoMetaTable() error { @@ -845,7 +845,11 @@ func (dwr DBWrapper) deleteRepoMetaTable() error { TableName: aws.String(dwr.RepoMetaTablename), }) - return err + if temp := new(types.ResourceNotFoundException); errors.As(err, &temp) { + return nil + } + + return dwr.waitTableToBeDeleted(dwr.RepoMetaTablename) } func (dwr DBWrapper) ResetRepoMetaTable() error { @@ -857,6 +861,69 @@ func (dwr DBWrapper) ResetRepoMetaTable() error { return dwr.createRepoMetaTable() } +func (dwr DBWrapper) waitTableToBeCreated(tableName string) error { + const ( + timeoutValue = time.Second * 5 + sleepTimeBetweenRequests = time.Millisecond * 50 + ) + + timeout := time.After(timeoutValue) + + for { + select { + case <-timeout: + return zerr.ErrTimeout + default: + output, err := dwr.Client.DescribeTable(context.Background(), &dynamodb.DescribeTableInput{ + TableName: &tableName, + }) + if output != nil && output.Table.TableStatus == types.TableStatusActive { + return nil + } + + if temp := new(types.ResourceNotFoundException); errors.As(err, &temp) { + // try again later + time.Sleep(sleepTimeBetweenRequests) + } else { // we have a different error + return err + } + } + } +} + +func (dwr DBWrapper) waitTableToBeDeleted(tableName string) error { + const ( + timeoutValue = time.Second * 5 + sleepTimeBetweenRequests = time.Millisecond * 50 + ) + + timeout := time.After(timeoutValue) + + for { + select { + case <-timeout: + return zerr.ErrTimeout + default: + output, err := dwr.Client.DescribeTable(context.Background(), &dynamodb.DescribeTableInput{ + TableName: &tableName, + }) + if output != nil && output.Table.TableStatus == types.TableStatusDeleting { + time.Sleep(sleepTimeBetweenRequests) + + continue + } + + if err != nil { + if temp := new(types.ResourceNotFoundException); !errors.As(err, &temp) { + return err + } + + return nil + } + } + } +} + func (dwr DBWrapper) createManifestDataTable() error { _, err := dwr.Client.CreateTable(context.Background(), &dynamodb.CreateTableInput{ TableName: aws.String(dwr.ManifestDataTablename), @@ -875,11 +942,11 @@ func (dwr DBWrapper) createManifestDataTable() error { BillingMode: types.BillingModePayPerRequest, }) - if err != nil && strings.Contains(err.Error(), "Table already exists") { - return nil + if err != nil && !strings.Contains(err.Error(), "Table already exists") { + return err } - return err + return dwr.waitTableToBeCreated(dwr.ManifestDataTablename) } func (dwr *DBWrapper) createVersionTable() error { @@ -899,9 +966,17 @@ func (dwr *DBWrapper) createVersionTable() error { }, BillingMode: types.BillingModePayPerRequest, }) + if err != nil { + if strings.Contains(err.Error(), "Table already exists") { + return nil + } - if err != nil && strings.Contains(err.Error(), "Table already exists") { - return nil + return err + } + + err = dwr.waitTableToBeCreated(dwr.VersionTablename) + if err != nil { + return err } if err == nil { @@ -931,7 +1006,7 @@ func (dwr *DBWrapper) createVersionTable() error { } } - return err + return nil } func (dwr *DBWrapper) getDBVersion() (string, error) { @@ -964,7 +1039,11 @@ func (dwr DBWrapper) deleteManifestDataTable() error { TableName: aws.String(dwr.ManifestDataTablename), }) - return err + if temp := new(types.ResourceNotFoundException); errors.As(err, &temp) { + return nil + } + + return dwr.waitTableToBeDeleted(dwr.ManifestDataTablename) } func (dwr DBWrapper) ResetManifestDataTable() error { @@ -973,5 +1052,10 @@ func (dwr DBWrapper) ResetManifestDataTable() error { return err } - return dwr.createManifestDataTable() + err = dwr.createManifestDataTable() + if err != nil { + return err + } + + return dwr.waitTableToBeCreated(dwr.ManifestDataTablename) }