diff --git a/aci/volumes.go b/aci/volumes.go index 3ce505bc..0b992a52 100644 --- a/aci/volumes.go +++ b/aci/volumes.go @@ -19,6 +19,7 @@ package aci import ( "context" "fmt" + "github.com/Azure/go-autorest/autorest/to" "github.com/docker/compose-cli/aci/login" "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-06-01/storage" @@ -96,6 +97,10 @@ func (cs *aciVolumeService) Create(ctx context.Context, options interface{}) (vo if err != nil { return volumes.Volume{}, err } + err = future.WaitForCompletionRef(ctx, accountClient.Client) + if err != nil { + return volumes.Volume{}, err + } account, err = future.Result(accountClient) if err != nil { return volumes.Volume{}, err @@ -130,10 +135,11 @@ func toVolume(account storage.Account, fileShareName string) volumes.Volume { func defaultStorageAccountParams(aciContext store.AciContext) storage.AccountCreateParameters { return storage.AccountCreateParameters{ - Location: &aciContext.Location, + Location: to.StringPtr(aciContext.Location), Sku: &storage.Sku{ Name: storage.StandardLRS, - Tier: storage.Standard, }, + Kind:storage.StorageV2, + AccountPropertiesCreateParameters: &storage.AccountPropertiesCreateParameters{}, } } diff --git a/tests/aci-e2e/e2e-aci_test.go b/tests/aci-e2e/e2e-aci_test.go index a31335d4..2a360f6e 100644 --- a/tests/aci-e2e/e2e-aci_test.go +++ b/tests/aci-e2e/e2e-aci_test.go @@ -39,7 +39,6 @@ import ( "gotest.tools/v3/poll" "github.com/Azure/azure-sdk-for-go/profiles/2019-03-01/resources/mgmt/resources" - azure_storage "github.com/Azure/azure-sdk-for-go/profiles/2019-03-01/storage/mgmt/storage" "github.com/Azure/azure-storage-file-go/azfile" "github.com/Azure/go-autorest/autorest/to" @@ -131,7 +130,7 @@ func TestContainerRunVolume(t *testing.T) { sID, rg := setupTestResourceGroup(t, c) const ( - testShareName = "dockertestshare" + fileshareName = "dockertestshare" testFileContent = "Volume mounted successfully!" testFileName = "index.html" ) @@ -142,31 +141,56 @@ func TestContainerRunVolume(t *testing.T) { Location: location, ResourceGroup: rg, } - saName := "e2e" + strconv.Itoa(int(time.Now().UnixNano())) - _, cleanupSa := createStorageAccount(t, aciContext, saName) - t.Cleanup(func() { - if err := cleanupSa(); err != nil { - t.Error(err) - } - }) - keys := getStorageKeys(t, aciContext, saName) - assert.Assert(t, len(keys) > 0) - k := *keys[0].Value - cred, u := createFileShare(t, k, testShareName, saName) - uploadFile(t, *cred, u.String(), testFileName, testFileContent) // Used in subtests var ( - container string - hostIP string - endpoint string + container string + hostIP string + endpoint string + volumeID string + accountName = "e2e" + strconv.Itoa(int(time.Now().UnixNano())) ) + t.Run("Create volumes", func(t *testing.T) { + c.RunDockerCmd("volume", "create", "--storage-account", accountName, "--fileshare", fileshareName) + }) + t.Cleanup(func() { deleteStorageAccount(t, aciContext, accountName) }) + + t.Run("Create second fileshare", func(t *testing.T) { + c.RunDockerCmd("volume", "create", "--storage-account", accountName, "--fileshare", "dockertestshare2") + }) + + t.Run("list volumes", func(t *testing.T) { + res := c.RunDockerCmd("volume", "ls") + out := strings.Split(strings.TrimSpace(res.Stdout()), "\n") + firstAccount := out[1] + fields := strings.Fields(firstAccount) + volumeID = accountName + "@" + fileshareName + assert.Equal(t, fields[0], volumeID) + assert.Equal(t, fields[1], fileshareName) + secondAccount := out[2] + fields = strings.Fields(secondAccount) + assert.Equal(t, fields[0], accountName + "@dockertestshare2") + assert.Equal(t, fields[1], "dockertestshare2") + //assert.Assert(t, fields[2], strings.Contains(firstAccount, fmt.Sprintf("Fileshare %s in %s storage account", fileshareName, accountName))) + }) + + t.Run("upload file", func(t *testing.T) { + storageLogin := login.StorageLogin{AciContext: aciContext} + + key, err := storageLogin.GetAzureStorageAccountKey(context.TODO(), accountName) + assert.NilError(t, err) + cred, err := azfile.NewSharedKeyCredential(accountName, key) + assert.NilError(t, err) + u, _ := url.Parse(fmt.Sprintf("https://%s.file.core.windows.net/%s", accountName, fileshareName)) + uploadFile(t, *cred, u.String(), testFileName, testFileContent) + }) + t.Run("run", func(t *testing.T) { mountTarget := "/usr/share/nginx/html" res := c.RunDockerCmd( "run", "-d", - "-v", fmt.Sprintf("%s@%s:%s", saName, testShareName, mountTarget), + "-v", fmt.Sprintf("%s:%s", volumeID, mountTarget), "-p", "80:80", "nginx", ) @@ -637,35 +661,12 @@ func createAciContextAndUseIt(t *testing.T, c *E2eCLI, sID, rgName string) { res.Assert(t, icmd.Expected{Out: contextName + " *"}) } -func createStorageAccount(t *testing.T, aciContext store.AciContext, name string) (azure_storage.Account, func() error) { - account, err := storage.CreateStorageAccount(context.TODO(), aciContext, name) - assert.Check(t, is.Nil(err)) - assert.Check(t, is.Equal(*(account.Name), name)) - return account, func() error { return deleteStorageAccount(aciContext, name) } -} - -func deleteStorageAccount(aciContext store.AciContext, name string) error { +func deleteStorageAccount(t *testing.T, aciContext store.AciContext, name string) { + fmt.Printf(" [%s] deleting storage account %s\n", t.Name(), name) _, err := storage.DeleteStorageAccount(context.TODO(), aciContext, name) - return err -} - -func getStorageKeys(t *testing.T, aciContext store.AciContext, saName string) []azure_storage.AccountKey { - l, err := storage.ListKeys(context.TODO(), aciContext, saName) - assert.NilError(t, err) - assert.Assert(t, l.Keys != nil) - return *l.Keys -} - -func createFileShare(t *testing.T, key, share, storageAccount string) (*azfile.SharedKeyCredential, *url.URL) { - // Create a ShareURL object that wraps a soon-to-be-created share's URL and a default pipeline. - u, _ := url.Parse(fmt.Sprintf("https://%s.file.core.windows.net/%s", storageAccount, share)) - cred, err := azfile.NewSharedKeyCredential(storageAccount, key) - assert.NilError(t, err) - - shareURL := azfile.NewShareURL(*u, azfile.NewPipeline(cred, azfile.PipelineOptions{})) - _, err = shareURL.Create(context.TODO(), azfile.Metadata{}, 0) - assert.NilError(t, err) - return cred, u + if err != nil { + t.Error(err) + } } func uploadFile(t *testing.T, cred azfile.SharedKeyCredential, baseURL, fileName, content string) { diff --git a/tests/aci-e2e/storage/storage.go b/tests/aci-e2e/storage/storage.go index 77eff6f0..9e83d1f3 100644 --- a/tests/aci-e2e/storage/storage.go +++ b/tests/aci-e2e/storage/storage.go @@ -18,76 +18,21 @@ package storage import ( "context" - "errors" - - "github.com/Azure/azure-sdk-for-go/profiles/2019-03-01/storage/mgmt/storage" "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/autorest/to" - "github.com/docker/compose-cli/aci/login" "github.com/docker/compose-cli/context/store" ) -// CreateStorageAccount creates a new storage account. -func CreateStorageAccount(ctx context.Context, aciContext store.AciContext, accountName string) (storage.Account, error) { - storageAccountsClient := getStorageAccountsClient(aciContext) - result, err := storageAccountsClient.CheckNameAvailability( - ctx, - storage.AccountCheckNameAvailabilityParameters{ - Name: to.StringPtr(accountName), - Type: to.StringPtr("Microsoft.Storage/storageAccounts"), - }) - - if err != nil { - return storage.Account{}, err - } - if !*result.NameAvailable { - return storage.Account{}, errors.New("storage account name already exists" + accountName) - } - - future, err := storageAccountsClient.Create( - ctx, - aciContext.ResourceGroup, - accountName, - storage.AccountCreateParameters{ - Sku: &storage.Sku{ - Name: storage.StandardLRS, - }, - Location: to.StringPtr(aciContext.Location), - AccountPropertiesCreateParameters: &storage.AccountPropertiesCreateParameters{}}) - if err != nil { - return storage.Account{}, err - } - err = future.WaitForCompletionRef(ctx, storageAccountsClient.Client) - if err != nil { - return storage.Account{}, err - } - return future.Result(storageAccountsClient) -} // DeleteStorageAccount deletes a given storage account func DeleteStorageAccount(ctx context.Context, aciContext store.AciContext, accountName string) (autorest.Response, error) { - storageAccountsClient := getStorageAccountsClient(aciContext) + storageAccountsClient, err := login.NewStorageAccountsClient(aciContext.SubscriptionID) + if err != nil { + return autorest.Response{}, err + } response, err := storageAccountsClient.Delete(ctx, aciContext.ResourceGroup, accountName) if err != nil { return autorest.Response{}, err } return response, err -} - -// ListKeys lists the storage account keys -func ListKeys(ctx context.Context, aciContext store.AciContext, accountName string) (storage.AccountListKeysResult, error) { - storageAccountsClient := getStorageAccountsClient(aciContext) - keys, err := storageAccountsClient.ListKeys(ctx, aciContext.ResourceGroup, accountName) - if err != nil { - return storage.AccountListKeysResult{}, err - } - return keys, nil -} - -func getStorageAccountsClient(aciContext store.AciContext) storage.AccountsClient { - storageAccountsClient := storage.NewAccountsClient(aciContext.SubscriptionID) - autho, _ := login.NewAuthorizerFromLogin() - storageAccountsClient.Authorizer = autho - return storageAccountsClient -} +} \ No newline at end of file