Skip to content

Commit

Permalink
Merge pull request #1304 from terraform-providers/blob_content_type
Browse files Browse the repository at this point in the history
Introduce `content_type` to `azurerm_storage_blob`
  • Loading branch information
katbyte authored Jun 12, 2018
2 parents 07622b7 + 96d8258 commit 30077d9
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 4 deletions.
61 changes: 57 additions & 4 deletions azurerm/resource_arm_storage_blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func resourceArmStorageBlob() *schema.Resource {
return &schema.Resource{
Create: resourceArmStorageBlobCreate,
Read: resourceArmStorageBlobRead,
Update: resourceArmStorageBlobUpdate,
Exists: resourceArmStorageBlobExists,
Delete: resourceArmStorageBlobDelete,

Expand Down Expand Up @@ -53,6 +54,12 @@ func resourceArmStorageBlob() *schema.Resource {
Default: 0,
ValidateFunc: validateArmStorageBlobSize,
},
"content_type": {
Type: schema.TypeString,
Optional: true,
Default: "application/octet-stream",
ConflictsWith: []string{"source_uri"},
},
"source": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -149,6 +156,7 @@ func resourceArmStorageBlobCreate(d *schema.ResourceData, meta interface{}) erro
blobType := d.Get("type").(string)
cont := d.Get("storage_container_name").(string)
sourceUri := d.Get("source_uri").(string)
contentType := d.Get("content_type").(string)

log.Printf("[INFO] Creating blob %q in storage account %q", name, storageAccountName)
if sourceUri != "" {
Expand All @@ -174,7 +182,7 @@ func resourceArmStorageBlobCreate(d *schema.ResourceData, meta interface{}) erro
if source != "" {
parallelism := d.Get("parallelism").(int)
attempts := d.Get("attempts").(int)
if err := resourceArmStorageBlobBlockUploadFromSource(cont, name, source, blobClient, parallelism, attempts); err != nil {
if err := resourceArmStorageBlobBlockUploadFromSource(cont, name, source, contentType, blobClient, parallelism, attempts); err != nil {
return fmt.Errorf("Error creating storage blob on Azure: %s", err)
}
}
Expand All @@ -183,7 +191,7 @@ func resourceArmStorageBlobCreate(d *schema.ResourceData, meta interface{}) erro
if source != "" {
parallelism := d.Get("parallelism").(int)
attempts := d.Get("attempts").(int)
if err := resourceArmStorageBlobPageUploadFromSource(cont, name, source, blobClient, parallelism, attempts); err != nil {
if err := resourceArmStorageBlobPageUploadFromSource(cont, name, source, contentType, blobClient, parallelism, attempts); err != nil {
return fmt.Errorf("Error creating storage blob on Azure: %s", err)
}
} else {
Expand All @@ -193,6 +201,7 @@ func resourceArmStorageBlobCreate(d *schema.ResourceData, meta interface{}) erro
container := blobClient.GetContainerReference(cont)
blob := container.GetBlobReference(name)
blob.Properties.ContentLength = size
blob.Properties.ContentType = contentType
err := blob.PutPageBlob(options)
if err != nil {
return fmt.Errorf("Error creating storage blob on Azure: %s", err)
Expand All @@ -210,7 +219,7 @@ type resourceArmStorageBlobPage struct {
section *io.SectionReader
}

func resourceArmStorageBlobPageUploadFromSource(container, name, source string, client *storage.BlobStorageClient, parallelism, attempts int) error {
func resourceArmStorageBlobPageUploadFromSource(container, name, source, contentType string, client *storage.BlobStorageClient, parallelism, attempts int) error {
workerCount := parallelism * runtime.NumCPU()

file, err := os.Open(source)
Expand All @@ -228,6 +237,7 @@ func resourceArmStorageBlobPageUploadFromSource(container, name, source string,
containerRef := client.GetContainerReference(container)
blob := containerRef.GetBlobReference(name)
blob.Properties.ContentLength = blobSize
blob.Properties.ContentType = contentType
err = blob.PutPageBlob(options)
if err != nil {
return fmt.Errorf("Error creating storage blob on Azure: %s", err)
Expand Down Expand Up @@ -387,7 +397,7 @@ type resourceArmStorageBlobBlock struct {
id string
}

func resourceArmStorageBlobBlockUploadFromSource(container, name, source string, client *storage.BlobStorageClient, parallelism, attempts int) error {
func resourceArmStorageBlobBlockUploadFromSource(container, name, source, contentType string, client *storage.BlobStorageClient, parallelism, attempts int) error {
workerCount := parallelism * runtime.NumCPU()

file, err := os.Open(source)
Expand Down Expand Up @@ -432,6 +442,7 @@ func resourceArmStorageBlobBlockUploadFromSource(container, name, source string,

containerReference := client.GetContainerReference(container)
blobReference := containerReference.GetBlobReference(name)
blobReference.Properties.ContentType = contentType
options := &storage.PutBlockListOptions{}
err = blobReference.PutBlockList(blockList, options)
if err != nil {
Expand Down Expand Up @@ -524,6 +535,40 @@ func resourceArmStorageBlobBlockUploadWorker(ctx resourceArmStorageBlobBlockUplo
}
}

func resourceArmStorageBlobUpdate(d *schema.ResourceData, meta interface{}) error {
armClient := meta.(*ArmClient)
ctx := armClient.StopContext

resourceGroupName := d.Get("resource_group_name").(string)
storageAccountName := d.Get("storage_account_name").(string)

blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(ctx, resourceGroupName, storageAccountName)
if err != nil {
return fmt.Errorf("Error getting storage account %s: %+v", storageAccountName, err)
}
if !accountExists {
return fmt.Errorf("Storage account %s not found in resource group %s", storageAccountName, resourceGroupName)
}

name := d.Get("name").(string)
storageContainerName := d.Get("storage_container_name").(string)

container := blobClient.GetContainerReference(storageContainerName)
blob := container.GetBlobReference(name)

if d.HasChange("content_type") {
blob.Properties.ContentType = d.Get("content_type").(string)
}

options := &storage.SetBlobPropertiesOptions{}
err = blob.SetProperties(options)
if err != nil {
return fmt.Errorf("Error setting properties of blob %s (container %s, storage account %s): %+v", name, storageContainerName, storageAccountName, err)
}

return nil
}

func resourceArmStorageBlobRead(d *schema.ResourceData, meta interface{}) error {
armClient := meta.(*ArmClient)
ctx := armClient.StopContext
Expand Down Expand Up @@ -556,6 +601,14 @@ func resourceArmStorageBlobRead(d *schema.ResourceData, meta interface{}) error

container := blobClient.GetContainerReference(storageContainerName)
blob := container.GetBlobReference(name)

options := &storage.GetBlobPropertiesOptions{}
err = blob.GetProperties(options)
if err != nil {
return fmt.Errorf("Error getting properties of blob %s (container %s, storage account %s): %+v", name, storageContainerName, storageAccountName, err)
}
d.Set("content_type", blob.Properties.ContentType)

url := blob.GetURL()
if url == "" {
log.Printf("[INFO] URL for %q is empty", name)
Expand Down
87 changes: 87 additions & 0 deletions azurerm/resource_arm_storage_blob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,51 @@ func TestAccAzureRMStorageBlob_source_uri(t *testing.T) {
})
}

func TestAccAzureRMStorageBlobBlock_blockContentType(t *testing.T) {
resourceName := "azurerm_storage_blob.source"
ri := acctest.RandInt()
rs1 := strings.ToLower(acctest.RandString(11))
sourceBlob, err := ioutil.TempFile("", "")
if err != nil {
t.Fatalf("Failed to create local source blob file")
}

_, err = io.CopyN(sourceBlob, rand.Reader, 25*1024*1024)
if err != nil {
t.Fatalf("Failed to write random test to source blob")
}

err = sourceBlob.Close()
if err != nil {
t.Fatalf("Failed to close source blob")
}

config := testAccAzureRMStorageBlobPage_blockContentType(ri, rs1, testLocation(), sourceBlob.Name(), "text/plain")
updateConfig := testAccAzureRMStorageBlobPage_blockContentType(ri, rs1, testLocation(), sourceBlob.Name(), "text/vnd.terraform.acctest.tmpfile")

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMStorageBlobDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMStorageBlobExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "content_type", "text/plain"),
),
},
{
Config: updateConfig,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMStorageBlobExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "content_type", "text/vnd.terraform.acctest.tmpfile"),
),
},
},
})
}

func testCheckAzureRMStorageBlobExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {

Expand Down Expand Up @@ -666,3 +711,45 @@ resource "azurerm_storage_blob" "destination" {
}
`, rInt, location, rString, sourceBlobName)
}

func testAccAzureRMStorageBlobPage_blockContentType(rInt int, rString, location string, sourceBlobName, contentType string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_storage_account" "source" {
name = "acctestacc%s"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
account_tier = "Standard"
account_replication_type = "LRS"
tags {
environment = "staging"
}
}
resource "azurerm_storage_container" "source" {
name = "source"
resource_group_name = "${azurerm_resource_group.test.name}"
storage_account_name = "${azurerm_storage_account.source.name}"
container_access_type = "blob"
}
resource "azurerm_storage_blob" "source" {
name = "source.vhd"
resource_group_name = "${azurerm_resource_group.test.name}"
storage_account_name = "${azurerm_storage_account.source.name}"
storage_container_name = "${azurerm_storage_container.source.name}"
type = "page"
source = "%s"
content_type = "%s"
parallelism = 3
attempts = 3
}
`, rInt, location, rString, sourceBlobName, contentType)
}
2 changes: 2 additions & 0 deletions website/docs/r/storage_blob.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ The following arguments are supported:

* `size` - (Optional) Used only for `page` blobs to specify the size in bytes of the blob to be created. Must be a multiple of 512. Defaults to 0.

* `content_type` - (Optional) The content type of the storage blob. Cannot be defined if `source_uri` is defined. Defaults to `application/octet-stream`.

* `source` - (Optional) An absolute path to a file on the local system. Cannot be defined if `source_uri` is defined.

* `source_uri` - (Optional) The URI of an existing blob, or a file in the Azure File service, to use as the source contents
Expand Down

0 comments on commit 30077d9

Please sign in to comment.