Skip to content

Commit

Permalink
bugfix: encryption scope must be specified when updating storage blog…
Browse files Browse the repository at this point in the history
… metadata
  • Loading branch information
manicminer committed Apr 9, 2024
1 parent 7f9a098 commit 4d1d622
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 6 deletions.
27 changes: 21 additions & 6 deletions internal/services/storage/storage_blob_resource.go
Expand Up @@ -10,6 +10,7 @@ import (
"strings"
"time"

"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/terraform-provider-azurerm/helpers/tf"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
Expand All @@ -19,7 +20,6 @@ import (
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
"github.com/hashicorp/terraform-provider-azurerm/internal/timeouts"
"github.com/hashicorp/terraform-provider-azurerm/utils"
"github.com/tombuildsstuff/giovanni/storage/2023-11-03/blob/accounts"
"github.com/tombuildsstuff/giovanni/storage/2023-11-03/blob/blobs"
)
Expand Down Expand Up @@ -285,11 +285,24 @@ func resourceStorageBlobUpdate(d *pluginsdk.ResourceData, meta interface{}) erro
return fmt.Errorf("building Blobs Client: %v", err)
}

log.Printf("[INFO] Retrieving %s", id)
input := blobs.GetPropertiesInput{}
props, err := blobsClient.GetProperties(ctx, id.ContainerName, id.BlobName, input)
if err != nil {
if response.WasNotFound(props.HttpResponse) {
log.Printf("[INFO] Blob %q was not found in Container %q / Account %q - assuming removed & removing from state...", id.BlobName, id.ContainerName, id.AccountId.AccountName)
d.SetId("")
return nil
}

return fmt.Errorf("retrieving properties for %s: %v", id, err)
}

if d.HasChange("content_type") || d.HasChange("cache_control") {
log.Printf("[DEBUG] Updating Properties for %s...", id)
input := blobs.SetPropertiesInput{
ContentType: utils.String(d.Get("content_type").(string)),
CacheControl: utils.String(d.Get("cache_control").(string)),
ContentType: pointer.To(d.Get("content_type").(string)),
CacheControl: pointer.To(d.Get("cache_control").(string)),
}

// `content_md5` is `ForceNew` but must be included in the `SetPropertiesInput` update payload, or it will be zeroed on the blob.
Expand All @@ -298,10 +311,8 @@ func resourceStorageBlobUpdate(d *pluginsdk.ResourceData, meta interface{}) erro
if err != nil {
return fmt.Errorf("converting hex to base64 encoding for content_md5: %v", err)
}

input.ContentMD5 = utils.String(data)
input.ContentMD5 = pointer.To(data)
}

if _, err = blobsClient.SetProperties(ctx, id.ContainerName, id.BlobName, input); err != nil {
return fmt.Errorf("updating Properties for %s: %v", id, err)
}
Expand All @@ -314,6 +325,10 @@ func resourceStorageBlobUpdate(d *pluginsdk.ResourceData, meta interface{}) erro
input := blobs.SetMetaDataInput{
MetaData: ExpandMetaData(metaDataRaw),
}
// Encryption Scope must be specified when updating metadata
if props.EncryptionScope != "" {
input.EncryptionScope = pointer.To(props.EncryptionScope)
}
if _, err = blobsClient.SetMetaData(ctx, id.ContainerName, id.BlobName, input); err != nil {
return fmt.Errorf("updating MetaData for %s: %v", id, err)
}
Expand Down
138 changes: 138 additions & 0 deletions internal/services/storage/storage_blob_resource_test.go
Expand Up @@ -344,6 +344,43 @@ func TestAccStorageBlob_encryptionScope(t *testing.T) {
})
}

func TestAccStorageBlob_encryptionScopeUpdate(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_storage_blob", "test")
r := StorageBlobResource{}
content := "Wubba Lubba Dub Dub"

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.encryptionScope(data, content),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("parallelism", "size", "source_content", "type"),
{
Config: r.encryptionScopeUpdateMetadata(data, content),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("parallelism", "size", "source_content", "type"),
{
Config: r.encryptionScopeUpdateProperties(data, content),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("parallelism", "size", "source_content", "type"),
{
Config: r.encryptionScopeUpdateAccessTier(data, content),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("parallelism", "size", "source_content", "type"),
})
}

func TestAccStorageBlob_pageEmpty(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_storage_blob", "test")
r := StorageBlobResource{}
Expand Down Expand Up @@ -989,6 +1026,107 @@ EOT
`, template, data.RandomInteger, content)
}

func (r StorageBlobResource) encryptionScopeUpdateMetadata(data acceptance.TestData, content string) string {
template := r.template(data, "blob")
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
%[1]s
resource "azurerm_storage_encryption_scope" "test" {
name = "acctestEScontainer%[2]d"
storage_account_id = azurerm_storage_account.test.id
source = "Microsoft.Storage"
}
resource "azurerm_storage_blob" "test" {
name = "rick.morty"
storage_account_name = azurerm_storage_account.test.name
storage_container_name = azurerm_storage_container.test.name
type = "Block"
encryption_scope = azurerm_storage_encryption_scope.test.name
source_content = <<EOT
%[3]s
EOT
metadata = {
hello = "world"
}
}
`, template, data.RandomInteger, content)
}

func (r StorageBlobResource) encryptionScopeUpdateProperties(data acceptance.TestData, content string) string {
template := r.template(data, "blob")
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
%[1]s
resource "azurerm_storage_encryption_scope" "test" {
name = "acctestEScontainer%[2]d"
storage_account_id = azurerm_storage_account.test.id
source = "Microsoft.Storage"
}
resource "azurerm_storage_blob" "test" {
name = "rick.morty"
storage_account_name = azurerm_storage_account.test.name
storage_container_name = azurerm_storage_container.test.name
type = "Block"
encryption_scope = azurerm_storage_encryption_scope.test.name
source_content = <<EOT
%[3]s
EOT
metadata = {
hello = "world"
}
content_type = "text/plain"
}
`, template, data.RandomInteger, content)
}

func (r StorageBlobResource) encryptionScopeUpdateAccessTier(data acceptance.TestData, content string) string {
template := r.template(data, "blob")
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
%[1]s
resource "azurerm_storage_encryption_scope" "test" {
name = "acctestEScontainer%[2]d"
storage_account_id = azurerm_storage_account.test.id
source = "Microsoft.Storage"
}
resource "azurerm_storage_blob" "test" {
name = "rick.morty"
storage_account_name = azurerm_storage_account.test.name
storage_container_name = azurerm_storage_container.test.name
type = "Block"
encryption_scope = azurerm_storage_encryption_scope.test.name
source_content = <<EOT
%[3]s
EOT
metadata = {
hello = "world"
}
content_type = "text/plain"
access_tier = "Hot"
}
`, template, data.RandomInteger, content)
}

func (r StorageBlobResource) pageEmpty(data acceptance.TestData) string {
template := r.template(data, "private")
return fmt.Sprintf(`
Expand Down

0 comments on commit 4d1d622

Please sign in to comment.