2014-11-25 18:40:24 +00:00
|
|
|
package azure
|
|
|
|
|
|
|
|
import (
|
2023-06-01 14:19:34 +00:00
|
|
|
"context"
|
2014-11-25 18:40:24 +00:00
|
|
|
"fmt"
|
2023-06-01 14:19:34 +00:00
|
|
|
"math/rand"
|
2014-11-25 18:40:24 +00:00
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
2020-08-24 11:18:39 +00:00
|
|
|
storagedriver "github.com/distribution/distribution/v3/registry/storage/driver"
|
|
|
|
"github.com/distribution/distribution/v3/registry/storage/driver/testsuites"
|
2023-04-29 15:08:47 +00:00
|
|
|
"gopkg.in/check.v1"
|
2014-11-25 18:40:24 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2020-02-21 03:58:17 +00:00
|
|
|
envAccountName = "AZURE_STORAGE_ACCOUNT_NAME"
|
|
|
|
envAccountKey = "AZURE_STORAGE_ACCOUNT_KEY"
|
|
|
|
envContainer = "AZURE_STORAGE_CONTAINER"
|
|
|
|
envRealm = "AZURE_STORAGE_REALM"
|
|
|
|
envRootDirectory = "AZURE_ROOT_DIRECTORY"
|
2014-11-25 18:40:24 +00:00
|
|
|
)
|
|
|
|
|
2023-06-01 14:19:34 +00:00
|
|
|
var azureDriverConstructor func() (storagedriver.StorageDriver, error)
|
2023-08-15 15:45:22 +00:00
|
|
|
var skipCheck func() string
|
2023-06-01 14:19:34 +00:00
|
|
|
|
2014-11-25 18:40:24 +00:00
|
|
|
// Hook up gocheck into the "go test" runner.
|
2023-04-29 15:08:47 +00:00
|
|
|
func Test(t *testing.T) { check.TestingT(t) }
|
2014-11-25 18:40:24 +00:00
|
|
|
|
|
|
|
func init() {
|
|
|
|
var (
|
2020-02-21 03:58:17 +00:00
|
|
|
accountName string
|
|
|
|
accountKey string
|
|
|
|
container string
|
|
|
|
realm string
|
|
|
|
rootDirectory string
|
2014-11-25 18:40:24 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
config := []struct {
|
2020-02-21 03:58:17 +00:00
|
|
|
env string
|
|
|
|
value *string
|
|
|
|
missingOk bool
|
2014-11-25 18:40:24 +00:00
|
|
|
}{
|
2023-08-15 15:45:22 +00:00
|
|
|
{envAccountName, &accountName, false},
|
2023-06-01 14:19:34 +00:00
|
|
|
{envAccountKey, &accountKey, true},
|
|
|
|
{envContainer, &container, true},
|
|
|
|
{envRealm, &realm, true},
|
2020-02-21 03:58:17 +00:00
|
|
|
{envRootDirectory, &rootDirectory, true},
|
2014-11-25 18:40:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
missing := []string{}
|
|
|
|
for _, v := range config {
|
|
|
|
*v.value = os.Getenv(v.env)
|
2020-02-21 03:58:17 +00:00
|
|
|
if *v.value == "" && !v.missingOk {
|
2014-11-25 18:40:24 +00:00
|
|
|
missing = append(missing, v.env)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-01 14:19:34 +00:00
|
|
|
azureDriverConstructor = func() (storagedriver.StorageDriver, error) {
|
2023-05-30 07:23:17 +00:00
|
|
|
parameters := map[string]interface{}{
|
|
|
|
"container": container,
|
|
|
|
"accountname": accountName,
|
|
|
|
"accountkey": accountKey,
|
|
|
|
"realm": realm,
|
|
|
|
"rootdirectory": rootDirectory,
|
2020-02-21 03:58:17 +00:00
|
|
|
}
|
2023-05-30 07:23:17 +00:00
|
|
|
params, err := NewParameters(parameters)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return New(params)
|
2014-11-25 18:40:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Skip Azure storage driver tests if environment variable parameters are not provided
|
2023-08-15 15:45:22 +00:00
|
|
|
skipCheck = func() string {
|
2014-11-25 18:40:24 +00:00
|
|
|
if len(missing) > 0 {
|
|
|
|
return fmt.Sprintf("Must set %s environment variables to run Azure tests", strings.Join(missing, ", "))
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2015-06-29 23:39:45 +00:00
|
|
|
testsuites.RegisterSuite(azureDriverConstructor, skipCheck)
|
2014-11-25 18:40:24 +00:00
|
|
|
}
|
2020-02-21 03:58:17 +00:00
|
|
|
|
2023-06-01 14:19:34 +00:00
|
|
|
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) {
|
2023-08-15 15:45:22 +00:00
|
|
|
if skipCheck() != "" {
|
|
|
|
t.Skip(skipCheck())
|
|
|
|
}
|
|
|
|
|
2023-06-01 14:19:34 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-21 03:58:17 +00:00
|
|
|
func TestParamParsing(t *testing.T) {
|
|
|
|
expectErrors := []map[string]interface{}{
|
|
|
|
{},
|
|
|
|
{"accountname": "acc1"},
|
|
|
|
}
|
|
|
|
for _, parameters := range expectErrors {
|
|
|
|
if _, err := NewParameters(parameters); err == nil {
|
|
|
|
t.Fatalf("Expected an error for parameter set: %v", parameters)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
input := []map[string]interface{}{
|
2023-08-15 15:45:22 +00:00
|
|
|
{"accountname": "acc1", "accountkey": "k1", "container": "c1", "copy_status_poll_max_retry": 1, "copy_status_poll_delay": "10ms"},
|
2020-02-21 03:58:17 +00:00
|
|
|
{"accountname": "acc1", "container": "c1", "credentials": map[string]interface{}{"type": "default"}},
|
|
|
|
{"accountname": "acc1", "container": "c1", "credentials": map[string]interface{}{"type": "client_secret", "clientid": "c1", "tenantid": "t1", "secret": "s1"}},
|
|
|
|
}
|
|
|
|
expecteds := []Parameters{
|
|
|
|
{
|
|
|
|
Container: "c1", AccountName: "acc1", AccountKey: "k1",
|
|
|
|
Realm: "core.windows.net", ServiceURL: "https://acc1.blob.core.windows.net",
|
2023-08-15 15:45:22 +00:00
|
|
|
CopyStatusPollMaxRetry: 1, CopyStatusPollDelay: "10ms",
|
2020-02-21 03:58:17 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Container: "c1", AccountName: "acc1", Credentials: Credentials{Type: "default"},
|
|
|
|
Realm: "core.windows.net", ServiceURL: "https://acc1.blob.core.windows.net",
|
2023-08-15 15:45:22 +00:00
|
|
|
CopyStatusPollMaxRetry: 5, CopyStatusPollDelay: "100ms",
|
2020-02-21 03:58:17 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Container: "c1", AccountName: "acc1",
|
|
|
|
Credentials: Credentials{Type: "client_secret", ClientID: "c1", TenantID: "t1", Secret: "s1"},
|
|
|
|
Realm: "core.windows.net", ServiceURL: "https://acc1.blob.core.windows.net",
|
2023-08-15 15:45:22 +00:00
|
|
|
CopyStatusPollMaxRetry: 5, CopyStatusPollDelay: "100ms",
|
2020-02-21 03:58:17 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for i, expected := range expecteds {
|
|
|
|
actual, err := NewParameters(input[i])
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Failed to parse: %v", input[i])
|
|
|
|
}
|
|
|
|
if *actual != expected {
|
|
|
|
t.Fatalf("Expected: %v != %v", *actual, expected)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|