Azure Blob Storage Upload

Octopus.Script exported 2016-01-21 by shawnmclean belongs to ‘Azure’ category.

Upload files in a directory to a specified Azure Storage blob container.

Parameters

When steps based on the template are included in a project’s deployment process, the parameters below can be set.

Copy Directory

CopyDirectory

Replicates files and directory under the Copy Directory. Eg. Content/CDN that is located at the root of the nuget package.

Publish Settings File

PublishSettingsFile

Absolute path on the tentacle to the Azure publishsettings file to use. Eg. C:\Azure\Azure.publishsettings

Storage Account

StorageAccount

The Azure Storage Account to use.

Storage Account Key

StorageAccountKey

The primary or secondary key for the Azure Storage Account.

Storage Container

StorageContainer

The storage container to use.

Nuget Package Step Name

NugetPackageStepName

Name of the previously-deployed package step that contains the Copy Directory.

Script body

Steps based on this template will execute the following PowerShell script.

function Find-InstallLocations {
    $result = @()
    $OctopusParameters.Keys | foreach {
        if ($_.EndsWith('].Output.Package.InstallationDirectoryPath')) {
            $result += $OctopusParameters[$_]
        }
    }
    return $result
}

function Find-InstallLocation($stepName) {
    $result = $OctopusParameters.Keys | where {
        $_.Equals("Octopus.Action[$stepName].Output.Package.InstallationDirectoryPath",  [System.StringComparison]::OrdinalIgnoreCase)
    } | select -first 1
 
    if ($result) {
        return $OctopusParameters[$result]
    }
 
    throw "No install location found for step: $stepName"
}

function Find-SingleInstallLocation {
    $all = @(Find-InstallLocations)
    if ($all.Length -eq 1) {
        return $all[0]
    }
    if ($all.Length -eq 0) {
        throw "No package steps found"
    }
    throw "Multiple package steps have run; please specify a single step"
}

# Check if Windows Azure Powershell is avaiable 
try{ 
    Import-Module Azure -ErrorAction Stop
}catch{
    throw "Windows Azure Powershell not found! Please make sure to install them from http://www.windowsazure.com/en-us/downloads/#cmd-line-tools" 
}

Import-AzurePublishSettingsFile $PublishSettingsFile

# The script has been tested on Powershell 3.0
Set-StrictMode -Version 3

$stepPath = ""
if (-not [string]::IsNullOrEmpty($NugetPackageStepName)) {
    Write-Host "Finding path to package step: $NugetPackageStepName"
    $stepPath = Find-InstallLocation $NugetPackageStepName
} else {
    $stepPath = Find-SingleInstallLocation
}
Write-Host "Package was installed to: $stepPath"

$fullPath = "$stepPath\$CopyDirectory"
Write-Host "Copying Files in: $fullPath"

# Get a list of files from the project folder
$files = @(ls -Path $fullPath -File -Recurse)

$fileCount = $files.Count
Write-Host "Found $fileCount Files: $files"

$context = New-AzureStorageContext `
    -StorageAccountName $StorageAccount `
    -StorageAccountKey $StorageAccountKey

if ($files -ne $null -and $files.Count -gt 0)
{
    # Create the storage container.
    $existingContainer = Get-AzureStorageContainer -Context $context | 
        Where-Object { $_.Name -like $StorageContainer }

    if (-not $existingContainer)
    {
        $newContainer = New-AzureStorageContainer `
                            -Context $context `
                            -Name $StorageContainer `
                            -Permission Blob
        "Storage container '" + $newContainer.Name + "' created."
    }

    # Upload the files to storage container.
    $fileCount = $files.Count
    $time = [DateTime]::UtcNow
    if ($files.Count -gt 0)
    {
        foreach ($file in $files) 
        {
            $blobFileName = $file.FullName.Replace($fullPath, '').TrimStart('\')
            $contentType = switch ([System.IO.Path]::GetExtension($file))
	        {
	            ".css" {"text/css"}
	            ".js" {"text/javascript"}
	            ".json" {"application/json"}
	            ".html" {"text/html"}
	            ".png" {"image/png"}
	            ".svg" {"image/svg+xml"}
	            default {"application/octet-stream"}
	        }

            Set-AzureStorageBlobContent `
                -Container $StorageContainer `
                -Context $context `
                -File $file.FullName `
                -Blob $blobFileName `
                -Properties @{ContentType=$contentType} `
                -Force
        }
    }

    $duration = [DateTime]::UtcNow - $time

    "Uploaded " + $files.Count + " files to blob container '" + $StorageContainer + "'."
    "Total upload time: " + $duration.TotalMinutes + " minutes."
}
else
{
    Write-Warning "No files found."
}

Provided under the Apache License version 2.0.

Report an issue

To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.

{
  "Id": "0b167d34-832e-4c96-8a8f-2ea0a6c0fe0c",
  "Name": "Azure Blob Storage Upload",
  "Description": "Upload files in a directory to a specified Azure Storage blob container.",
  "Version": 14,
  "ExportedAt": "2016-01-21T07:21:36.182+00:00",
  "ActionType": "Octopus.Script",
  "Author": "shawnmclean",
  "Parameters": [
    {
      "Name": "CopyDirectory",
      "Label": "Copy Directory",
      "HelpText": "Replicates files and directory under the Copy Directory.\nEg. `Content/CDN` that is located at the root of the nuget package.",
      "DefaultValue": null,
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Name": "PublishSettingsFile",
      "Label": "Publish Settings File",
      "HelpText": "Absolute path on the tentacle to the Azure publishsettings file to use.\nEg. `C:\\Azure\\Azure.publishsettings`",
      "DefaultValue": null,
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Name": "StorageAccount",
      "Label": "Storage Account",
      "HelpText": "The Azure Storage Account to use.",
      "DefaultValue": null,
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Name": "StorageAccountKey",
      "Label": "Storage Account Key",
      "HelpText": "The primary or secondary key for the Azure Storage Account.",
      "DefaultValue": null,
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Name": "StorageContainer",
      "Label": "Storage Container",
      "HelpText": "The storage container to use.",
      "DefaultValue": null,
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Name": "NugetPackageStepName",
      "Label": "Nuget Package Step Name",
      "HelpText": "Name of the previously-deployed package step that contains the Copy Directory.",
      "DefaultValue": null,
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    }
  ],
  "Properties": {
    "Octopus.Action.Script.ScriptBody": "function Find-InstallLocations {\n    $result = @()\n    $OctopusParameters.Keys | foreach {\n        if ($_.EndsWith('].Output.Package.InstallationDirectoryPath')) {\n            $result += $OctopusParameters[$_]\n        }\n    }\n    return $result\n}\n\nfunction Find-InstallLocation($stepName) {\n    $result = $OctopusParameters.Keys | where {\n        $_.Equals(\"Octopus.Action[$stepName].Output.Package.InstallationDirectoryPath\",  [System.StringComparison]::OrdinalIgnoreCase)\n    } | select -first 1\n \n    if ($result) {\n        return $OctopusParameters[$result]\n    }\n \n    throw \"No install location found for step: $stepName\"\n}\n\nfunction Find-SingleInstallLocation {\n    $all = @(Find-InstallLocations)\n    if ($all.Length -eq 1) {\n        return $all[0]\n    }\n    if ($all.Length -eq 0) {\n        throw \"No package steps found\"\n    }\n    throw \"Multiple package steps have run; please specify a single step\"\n}\n\n# Check if Windows Azure Powershell is avaiable \ntry{ \n    Import-Module Azure -ErrorAction Stop\n}catch{\n    throw \"Windows Azure Powershell not found! Please make sure to install them from http://www.windowsazure.com/en-us/downloads/#cmd-line-tools\" \n}\n\nImport-AzurePublishSettingsFile $PublishSettingsFile\n\n# The script has been tested on Powershell 3.0\nSet-StrictMode -Version 3\n\n$stepPath = \"\"\nif (-not [string]::IsNullOrEmpty($NugetPackageStepName)) {\n    Write-Host \"Finding path to package step: $NugetPackageStepName\"\n    $stepPath = Find-InstallLocation $NugetPackageStepName\n} else {\n    $stepPath = Find-SingleInstallLocation\n}\nWrite-Host \"Package was installed to: $stepPath\"\n\n$fullPath = \"$stepPath\\$CopyDirectory\"\nWrite-Host \"Copying Files in: $fullPath\"\n\n# Get a list of files from the project folder\n$files = @(ls -Path $fullPath -File -Recurse)\n\n$fileCount = $files.Count\nWrite-Host \"Found $fileCount Files: $files\"\n\n$context = New-AzureStorageContext `\n    -StorageAccountName $StorageAccount `\n    -StorageAccountKey $StorageAccountKey\n\nif ($files -ne $null -and $files.Count -gt 0)\n{\n    # Create the storage container.\n    $existingContainer = Get-AzureStorageContainer -Context $context | \n        Where-Object { $_.Name -like $StorageContainer }\n\n    if (-not $existingContainer)\n    {\n        $newContainer = New-AzureStorageContainer `\n                            -Context $context `\n                            -Name $StorageContainer `\n                            -Permission Blob\n        \"Storage container '\" + $newContainer.Name + \"' created.\"\n    }\n\n    # Upload the files to storage container.\n    $fileCount = $files.Count\n    $time = [DateTime]::UtcNow\n    if ($files.Count -gt 0)\n    {\n        foreach ($file in $files) \n        {\n            $blobFileName = $file.FullName.Replace($fullPath, '').TrimStart('\\')\n            $contentType = switch ([System.IO.Path]::GetExtension($file))\n\t        {\n\t            \".css\" {\"text/css\"}\n\t            \".js\" {\"text/javascript\"}\n\t            \".json\" {\"application/json\"}\n\t            \".html\" {\"text/html\"}\n\t            \".png\" {\"image/png\"}\n\t            \".svg\" {\"image/svg+xml\"}\n\t            default {\"application/octet-stream\"}\n\t        }\n\n            Set-AzureStorageBlobContent `\n                -Container $StorageContainer `\n                -Context $context `\n                -File $file.FullName `\n                -Blob $blobFileName `\n                -Properties @{ContentType=$contentType} `\n                -Force\n        }\n    }\n\n    $duration = [DateTime]::UtcNow - $time\n\n    \"Uploaded \" + $files.Count + \" files to blob container '\" + $StorageContainer + \"'.\"\n    \"Total upload time: \" + $duration.TotalMinutes + \" minutes.\"\n}\nelse\n{\n    Write-Warning \"No files found.\"\n}",
    "Octopus.Action.Script.Syntax": "PowerShell"
  },
  "Category": "Azure",
  "HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/azure-blob-storage-upload.json",
  "Website": "/step-templates/0b167d34-832e-4c96-8a8f-2ea0a6c0fe0c",
  "Logo": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADNQTFRF////AHjXf7vrv931QJrh7/f8EIDaIIncMJHfYKvmz+b3n8zw3+76j8Ttr9XycLPpUKLkkKvYFAAABGZJREFUeNrsnNmCqjoQRc1MEiD8/9cer7Yt2KBJZQC8ez07sKlKTQlcLgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzoUSnt8YxXlFuGHSbIaxvj+fip4btkLn1blkWLaF5v03yLhLOYlVuGYfMOMZzNGxCOzhjTJqFkXnjq3Dr1yyvPI3hGl3Ih3zzHHNKudRstRhX5O58vIcShY67Gq6EPIESlzUWvazaGAOGbvU7ArDu/g8M4o8opDZWvbvPzlL/MMBE8jT9T9W7PbAJlHPTBFRf9yVTEcs63msXz2UHLSgf650G/d5t+wjbxxB2UCMqGrk8/LFSD7uJMeNt5bcJCyQZyAe5Fo9KYfWS2flQrr4b4tpuzaeWjYs49rt9LHf9uZD7+VbyVi9EBNrjYjuq2sxQOrl+p+HuBVu45qvqfq691ttYFQ5KyKbyJgaIY/NGxrlWZwlwGvmvu1oY3PuAv0niTq6tZ78jk//9uc1r1r4lQki7y7sp2Tu4V1y2iLoqFTqi1lIGcpFiebrZNZ1dOkF0cCIlO8jQ47nCkam9Lilz9GhDF1I6XGLzfnhwDIIZVfI7+8SSgfHsijqXENOGJF5QorG4EcW0OrScqX/dDrXpr70Ut/BII+1OfECPuYz/NWxYmgrCsUskxPvyhgmrw+WGZ6lGTuOlIyCYWTFyWjpM5KIZRUIOwjRNYRQ6tZF9BXtk8hWAHPtLNJ727Fq0JSkC1FDRRF0Jalj0d5qVh2KEpM2TuSsCYTCT6ZkdmFYI9LrYp5QayWbo6NXlZwcRD/61pth5Fq5EX423QQxNjhqWvvklkljOLkYjrmphXPZOJOk6Pg7HKMsrtQKcowzZoK3rx1ZUelGMdQA/HaKkjAt2RgqpZeYqbNbH7Hp2ct4nqfSPOfe0ftiSTZJydOV6rG5bQbyLK+nRuCC0343PzDgiOXyQA5c14BTZi98uR/5KJ1SnatLdoO50WWBQZPTq0VgsklU3h932actuo17ayrHrb/3ykiegd3KbqF2wbV6RrlsJ07yLcpsWFTul9RyK6ZScr+tk7oNrFj0o7HQUlj4EiEvJ6rPLKSmlMZCrksl1OnLaRkxc+/HB1naMhNtT/6yM2bDs6azCRHrM3aVPN7aW8irD/10B8njpAMcsl8okXcdKrl4sPsLmQVy/Sj90ucPRc/d/Bxxj+dXSpCayen32D+hLi16MsIV8gfCXrYp6ySsiJKRUF0XXiLpVbFU+fNv4r7mOwhFsX4ZdwpSi1DYs2jb6ebZ9788cblTzMrYhu7sf/17IFdtuviJ2ioHA6pMHkoH4CLUeMBU7iGkxuM/YgcdderF9ibRdc7O982F1HpYhjfWUe+x5a6pjop9iNLfoePvlsdZdTSMwfxSmTY20Q0eHnUNzga1edeNmmqbg18aMVR1L9vwSXHF9TfIWBxpKLs2hj3eQeBC0USvp2HHF3eIkRdhFOd6ER8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/I/4J8AAo/80BciBec4AAAAASUVORK5CYII=",
  "$Meta": {
    "Type": "ActionTemplate"
  }
}

History

Page updated on Thursday, January 21, 2016