registry/storage/driver/azure: fix Move method

Something seems broken on azure/azure sdk side - it is currently not
possible to copy a blob of type AppendBlob using `CopyFromURL`.
Using the AppendBlob client via NewAppendBlobClient does not work
either.

According to Azure the correct way to do this is by using
StartCopyFromURL. Because this is an async operation, we need to do
polling ourselves. A simple backoff mechanism is used, where during each
iteration, the configured delay is multiplied by the retry number.

Also introduces two new config options for the Azure driver:
copy_status_poll_max_retry, and copy_status_poll_delay.

Signed-off-by: Flavian Missi <fmissi@redhat.com>
This commit is contained in:
Flavian Missi 2023-06-01 16:19:34 +02:00
parent ba46c769b3
commit 2b72c4d1ca
5 changed files with 149 additions and 29 deletions

View file

@ -1,7 +1,9 @@
package azure
import (
"context"
"fmt"
"math/rand"
"os"
"strings"
"testing"
@ -19,6 +21,8 @@ const (
envRootDirectory = "AZURE_ROOT_DIRECTORY"
)
var azureDriverConstructor func() (storagedriver.StorageDriver, error)
// Hook up gocheck into the "go test" runner.
func Test(t *testing.T) { check.TestingT(t) }
@ -36,10 +40,10 @@ func init() {
value *string
missingOk bool
}{
{envAccountName, &accountName, false},
{envAccountKey, &accountKey, false},
{envContainer, &container, false},
{envRealm, &realm, false},
{envAccountName, &accountName, true},
{envAccountKey, &accountKey, true},
{envContainer, &container, true},
{envRealm, &realm, true},
{envRootDirectory, &rootDirectory, true},
}
@ -51,7 +55,7 @@ func init() {
}
}
azureDriverConstructor := func() (storagedriver.StorageDriver, error) {
azureDriverConstructor = func() (storagedriver.StorageDriver, error) {
parameters := map[string]interface{}{
"container": container,
"accountname": accountName,
@ -77,6 +81,66 @@ func init() {
testsuites.RegisterSuite(azureDriverConstructor, skipCheck)
}
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
func randStringRunes(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
return string(b)
}
func TestCommitAfterMove(t *testing.T) {
driver, err := azureDriverConstructor()
if err != nil {
t.Fatalf("unexpected error creating azure driver: %v", err)
}
contents := randStringRunes(4 * 1024 * 1024)
sourcePath := "/source/file"
destPath := "/dest/file"
ctx := context.Background()
defer driver.Delete(ctx, sourcePath)
defer driver.Delete(ctx, destPath)
writer, err := driver.Writer(ctx, sourcePath, false)
if err != nil {
t.Fatalf("unexpected error from driver.Writer: %v", err)
}
_, err = writer.Write([]byte(contents))
if err != nil {
t.Fatalf("writer.Write: unexpected error: %v", err)
}
err = writer.Commit()
if err != nil {
t.Fatalf("writer.Commit: unexpected error: %v", err)
}
err = writer.Close()
if err != nil {
t.Fatalf("writer.Close: unexpected error: %v", err)
}
_, err = driver.GetContent(ctx, sourcePath)
if err != nil {
t.Fatalf("driver.GetContent(sourcePath): unexpected error: %v", err)
}
err = driver.Move(ctx, sourcePath, destPath)
if err != nil {
t.Fatalf("driver.Move: unexpected error: %v", err)
}
_, err = driver.GetContent(ctx, destPath)
if err != nil {
t.Fatalf("GetContent(destPath): unexpected error: %v", err)
}
}
func TestParamParsing(t *testing.T) {
expectErrors := []map[string]interface{}{
{},