diff --git a/backend/remote-state/azure/backend.go b/backend/remote-state/azure/backend.go index 4431d4f5f4..aa18d50592 100644 --- a/backend/remote-state/azure/backend.go +++ b/backend/remote-state/azure/backend.go @@ -4,7 +4,10 @@ import ( "context" "fmt" - "github.com/Azure/azure-sdk-for-go/arm/storage" + armStorage "github.com/Azure/azure-sdk-for-go/arm/storage" + "github.com/Azure/azure-sdk-for-go/storage" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/adal" "github.com/Azure/go-autorest/autorest/azure" "github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/helper/schema" @@ -157,18 +160,18 @@ func getAccessKey(d *schema.ResourceData, storageAccountName string, env azure.E return "", fmt.Errorf("resource_group_name and credentials must be provided when access_key is absent") } - oauthConfig, err := env.OAuthConfigForTenant(tenantID.(string)) + oauthConfig, err := adal.NewOAuthConfig(env.ActiveDirectoryEndpoint, tenantID.(string)) if err != nil { return "", err } - spt, err := azure.NewServicePrincipalToken(*oauthConfig, clientID.(string), clientSecret.(string), env.ResourceManagerEndpoint) + spt, err := adal.NewServicePrincipalToken(*oauthConfig, clientID.(string), clientSecret.(string), env.ResourceManagerEndpoint) if err != nil { return "", err } - accountsClient := storage.NewAccountsClientWithBaseURI(env.ResourceManagerEndpoint, subscriptionID.(string)) - accountsClient.Authorizer = spt + accountsClient := armStorage.NewAccountsClientWithBaseURI(env.ResourceManagerEndpoint, subscriptionID.(string)) + accountsClient.Authorizer = autorest.NewBearerAuthorizer(spt) keys, err := accountsClient.ListKeys(resourceGroupName.(string), storageAccountName) if err != nil { diff --git a/backend/remote-state/azure/backend_state.go b/backend/remote-state/azure/backend_state.go index c6c86f309e..c7bc02755f 100644 --- a/backend/remote-state/azure/backend_state.go +++ b/backend/remote-state/azure/backend_state.go @@ -5,7 +5,7 @@ import ( "sort" "strings" - "github.com/Azure/azure-sdk-for-go/arm/storage" + "github.com/Azure/azure-sdk-for-go/storage" "github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/state" "github.com/hashicorp/terraform/state/remote" @@ -57,7 +57,11 @@ func (b *Backend) DeleteState(name string) error { return fmt.Errorf("can't delete default state") } - return b.blobClient.DeleteBlob(b.containerName, b.path(name), nil) + containerReference := b.blobClient.GetContainerReference(b.containerName) + blobReference := containerReference.GetBlobReference(b.path(name)) + options := &storage.DeleteBlobOptions{} + + return blobReference.Delete(options) } func (b *Backend) State(name string) (state.State, error) { diff --git a/backend/remote-state/azure/backend_test.go b/backend/remote-state/azure/backend_test.go index 6164c75aa3..a08fb73f0d 100644 --- a/backend/remote-state/azure/backend_test.go +++ b/backend/remote-state/azure/backend_test.go @@ -6,8 +6,10 @@ import ( "testing" "github.com/Azure/azure-sdk-for-go/arm/resources/resources" - "github.com/Azure/azure-sdk-for-go/arm/storage" - "github.com/Azure/azure-storage-go" + armStorage "github.com/Azure/azure-sdk-for-go/arm/storage" + "github.com/Azure/azure-sdk-for-go/storage" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/adal" "github.com/Azure/go-autorest/autorest/azure" "github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/helper/acctest" @@ -121,14 +123,15 @@ func setupResources(t *testing.T, keyName string) testResources { } t.Logf("creating storage account %s", res.storageAccountName) - _, err = clients.storageAccountsClient.Create(res.resourceGroupName, res.storageAccountName, armStorage.AccountCreateParameters{ + _, createError := clients.storageAccountsClient.Create(res.resourceGroupName, res.storageAccountName, armStorage.AccountCreateParameters{ Sku: &armStorage.Sku{ Name: armStorage.StandardLRS, Tier: armStorage.Standard, }, Location: &location, }, make(chan struct{})) - if err != nil { + createErr := <-createError + if createErr != nil { destroyResources(t, res.resourceGroupName) t.Fatalf("failed to create test storage account: %s", err) } @@ -151,8 +154,9 @@ func setupResources(t *testing.T, keyName string) testResources { } t.Logf("creating container %s", res.containerName) - container := storageClient.GetBlobService().GetContainerReference(res.containerName) - err = container.Create() + blobService := storageClient.GetBlobService() + container := blobService.GetContainerReference(res.containerName) + err = container.Create(&storage.CreateContainerOptions{}) if err != nil { destroyResources(t, res.resourceGroupName) t.Fatalf("failed to create storage container: %s", err) @@ -169,7 +173,8 @@ func destroyResources(t *testing.T, resourceGroupName string) { t.Log("destroying created resources") // destroying is simple as deleting the resource group will destroy everything else - _, err := clients.groupsClient.Delete(resourceGroupName, make(chan struct{})) + _, deleteErr := clients.groupsClient.Delete(resourceGroupName, make(chan struct{})) + err := <-deleteErr if err != nil { t.Logf(warning, err) return @@ -206,21 +211,21 @@ func getTestClient(t *testing.T) testClient { } client.environment = env - oauthConfig, err := env.OAuthConfigForTenant(client.tenantID) + oauthConfig, err := adal.NewOAuthConfig(env.ActiveDirectoryEndpoint, client.tenantID) if err != nil { t.Fatalf("Failed to get OAuth config: %s", err) } - spt, err := azure.NewServicePrincipalToken(*oauthConfig, client.clientID, client.clientSecret, env.ResourceManagerEndpoint) + spt, err := adal.NewServicePrincipalToken(*oauthConfig, client.clientID, client.clientSecret, env.ResourceManagerEndpoint) if err != nil { t.Fatalf("Failed to create Service Principal Token: %s", err) } client.groupsClient = resources.NewGroupsClientWithBaseURI(env.ResourceManagerEndpoint, client.subscriptionID) - client.groupsClient.Authorizer = spt + client.groupsClient.Authorizer = autorest.NewBearerAuthorizer(spt) client.storageAccountsClient = armStorage.NewAccountsClientWithBaseURI(env.ResourceManagerEndpoint, client.subscriptionID) - client.storageAccountsClient.Authorizer = spt + client.storageAccountsClient.Authorizer = autorest.NewBearerAuthorizer(spt) return client } diff --git a/backend/remote-state/azure/client.go b/backend/remote-state/azure/client.go index bc503579f3..c37d2b92b0 100644 --- a/backend/remote-state/azure/client.go +++ b/backend/remote-state/azure/client.go @@ -8,7 +8,7 @@ import ( "log" "encoding/base64" - "github.com/Azure/azure-sdk-for-go/arm/storage" + "github.com/Azure/azure-sdk-for-go/storage" multierror "github.com/hashicorp/go-multierror" uuid "github.com/hashicorp/go-uuid" "github.com/hashicorp/terraform/state" @@ -30,7 +30,10 @@ type RemoteClient struct { } func (c *RemoteClient) Get() (*remote.Payload, error) { - blob, err := c.blobClient.GetBlob(c.containerName, c.keyName) + containerReference := c.blobClient.GetContainerReference(c.containerName) + blobReference := containerReference.GetBlobReference(c.keyName) + options := &storage.GetBlobOptions{} + blob, err := blobReference.Get(options) if err != nil { if storErr, ok := err.(storage.AzureStorageServiceError); ok { if storErr.Code == "BlobNotFound" { @@ -60,38 +63,40 @@ func (c *RemoteClient) Get() (*remote.Payload, error) { } func (c *RemoteClient) Put(data []byte) error { - headers := map[string]string{ - "Content-Type": "application/json", - } + setOptions := &storage.SetBlobPropertiesOptions{} + putOptions := &storage.PutBlobOptions{} + + containerReference := c.blobClient.GetContainerReference(c.containerName) + blobReference := containerReference.GetBlobReference(c.keyName) + + blobReference.Properties.ContentType = "application/json" + blobReference.Properties.ContentLength = int64(len(data)) if c.leaseID != "" { - headers[leaseHeader] = c.leaseID + setOptions.LeaseID = c.leaseID + putOptions.LeaseID = c.leaseID } - log.Print("[DEBUG] Uploading remote state to Azure") - - err := c.blobClient.CreateBlockBlobFromReader( - c.containerName, - c.keyName, - uint64(len(data)), - bytes.NewReader(data), - headers, - ) + reader := bytes.NewReader(data) + err := blobReference.CreateBlockBlobFromReader(reader, putOptions) if err != nil { - return fmt.Errorf("Failed to upload state: %v", err) + return err } - return nil + return blobReference.SetProperties(setOptions) } func (c *RemoteClient) Delete() error { - headers := map[string]string{} + containerReference := c.blobClient.GetContainerReference(c.containerName) + blobReference := containerReference.GetBlobReference(c.keyName) + options := &storage.DeleteBlobOptions{} + if c.leaseID != "" { - headers[leaseHeader] = c.leaseID + options.LeaseID = c.leaseID } - return c.blobClient.DeleteBlob(c.containerName, c.keyName, headers) + return blobReference.Delete(options) } func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) { @@ -119,7 +124,9 @@ func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) { } } - leaseID, err := c.blobClient.AcquireLease(c.containerName, c.keyName, -1, info.ID) + containerReference := c.blobClient.GetContainerReference(c.containerName) + blobReference := containerReference.GetBlobReference(c.keyName) + leaseID, err := blobReference.AcquireLease(-1, info.ID, &storage.LeaseOptions{}) if err != nil { if storErr, ok := err.(storage.AzureStorageServiceError); ok && storErr.Code != "BlobNotFound" { return "", getLockInfoErr(err) @@ -144,7 +151,7 @@ func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) { } } - leaseID, err = c.blobClient.AcquireLease(c.containerName, c.keyName, -1, info.ID) + leaseID, err = blobReference.AcquireLease(-1, info.ID, &storage.LeaseOptions{}) if err != nil { return "", getLockInfoErr(err) } @@ -161,12 +168,14 @@ func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) { } func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) { - meta, err := c.blobClient.GetBlobMetadata(c.containerName, c.keyName) + containerReference := c.blobClient.GetContainerReference(c.containerName) + blobReference := containerReference.GetBlobReference(c.keyName) + err := blobReference.GetMetadata(&storage.GetBlobMetadataOptions{}) if err != nil { return nil, err } - raw := meta[lockInfoMetaKey] + raw := blobReference.Metadata[lockInfoMetaKey] if raw == "" { return nil, fmt.Errorf("blob metadata %s was empty", lockInfoMetaKey) } @@ -187,22 +196,24 @@ func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) { // writes info to blob meta data, deletes metadata entry if info is nil func (c *RemoteClient) writeLockInfo(info *state.LockInfo) error { - meta, err := c.blobClient.GetBlobMetadata(c.containerName, c.keyName) + containerReference := c.blobClient.GetContainerReference(c.containerName) + blobReference := containerReference.GetBlobReference(c.keyName) + err := blobReference.GetMetadata(&storage.GetBlobMetadataOptions{}) if err != nil { return err } if info == nil { - delete(meta, lockInfoMetaKey) + delete(blobReference.Metadata, lockInfoMetaKey) } else { value := base64.StdEncoding.EncodeToString(info.Marshal()) - meta[lockInfoMetaKey] = value + blobReference.Metadata[lockInfoMetaKey] = value } - headers := map[string]string{ - leaseHeader: c.leaseID, + opts := &storage.SetBlobMetadataOptions{ + LeaseID: c.leaseID, } - return c.blobClient.SetBlobMetadata(c.containerName, c.keyName, meta, headers) + return blobReference.SetMetadata(opts) } @@ -226,7 +237,9 @@ func (c *RemoteClient) Unlock(id string) error { return lockErr } - err = c.blobClient.ReleaseLease(c.containerName, c.keyName, id) + containerReference := c.blobClient.GetContainerReference(c.containerName) + blobReference := containerReference.GetBlobReference(c.keyName) + err = blobReference.ReleaseLease(id, &storage.LeaseOptions{}) if err != nil { lockErr.Err = err return lockErr