After my last post I was a little bit dissatisfied with the fact that if you use the scripts frequently the blob storage container will fill up quite a bit. As already outlined this will affect the monthly charges billed to your account especially when you are deploying in a high frequency and have to deploy large packages. So I was looking for a solution to that.

So as we are already operating in a Windows Powershell environment I thought the best way to resolve this would be to provide a commandlet that does enable you to delete the deployment packages in the blob storage. So I created a small that of commandlets which enable you to interact with the Windows Azure blob storage based on the official StorageClient managed API. I packaged the commandlets into a SnapIn.

The available commandlets so far are:

Get-Storage This represents the base storage service with the elemental properties “SharedKey” and “StorageAccount” which are needed for almost every subsequent operation.
Get-Container Lists the container currently available in the blob storage account. This commandlet is not needed for the task of removing the deployment packages.
Get-Bloblist This commandlet lists the blobs of a specific container and holds a property of “BlobList” which can be used as a piping parameter for the Remove-Blob commandlet. It allows for simple filtering based on extensions with the “ExtensionFilter” parameter. So for our task you could filter for the “cspkg” extension to target all deployment packages.
Remove-Blob This commandlet removes the blobs provided via the “BlobList” parameter or all blobs in the container if no list is provided. So be careful in using this commandlet.

The code is attached to this blog post. I choose to provide it in a separate SnapIn package however you could also add it to the Windows Azure Service Management CmdLets project which is also provided as source code. If you use the package as is you need to install it once using the Installer Tool shipping with the .Net Framework. So you need to issue a command similar to this:

c:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe AzureCommandletCollection.dll

After doing so you can check if the AzureCommandletCollectionSnapIn is listed as a registered SanpIn using the command

Get-PSSnapin –registered

The output should look something like this:

azure_cmdlet1

Then finally in order to use it you need to add the SnapIn to the snapin to the active powershell session. You need to do that no matter if you want to use the commandlets interactively or from script. Issue the to do so.

Add-PSSnapin AzureCommandletCollectionSnapIn

With respect to integrating the removal task to our scripts I have then altered my deployment script to get rid of the deployment package right after the deployment. So the list of blobs should usually always only consist of one entry.

The changes are minimal. There are only two changes. The first is the part where we need to add the SnapIn to the session:

if(!($mgmtsnapin = Get-PSSnapin AzureManagementToolsSnapIn -erroraction silentlycontinue))
{
    Write-Host "Adding ManagementTools SnapIn...please wait"
    Add-PSSnapin AzureManagementToolsSnapIn
    if(!($storagesnapin = Get-PSSnapin AzureCommandletCollectionSnapIn -erroraction silentlycontinue))
    {
        Write-Host "Adding AzureCommandletCollection SnapIn...please wait"
        Add-PSSnapin AzureCommandletCollectionSnapIn
    }
}
 
The second change is the the actual removal task:
 
$storagekeys = Get-StorageKeys -ServiceName $storageservicename -SubscriptionId $subscriptionid -Certificate $cert
Get-Storage -StorageAccount $storageservicename -SharedKey $storagekeys.Primary 
| Get-Bloblist -ContainerName mydeployments -ExtensionFilter cspkg 
| Remove-Blob
 
So then we can outline the final script which looks like the following:
<#
    .Synopsis
        Will deploy and start a Windows Azure Service
    .Description
        Will deploy and start a Windows Azure Service        
    .Parameter servicename
        The name of the Azure service that will hold the deployment
    .Parameter thumbprint
        The thumbprint of a locally installed and valid certificate for accessing
        the Windows Azure Management Service
    .Parameter subscriptionid
        The ID for the subscription of the Azure Account hosting the respective service
    .Parameter slot
        The deployment slot in which the package shall be deployed <Production | Staging>
    .Parameter storageservicename
        The storage account that can be used to upload the deployment package
    .Parameter package
        The full qualified path to the deployment package
    .Parameter config
        The full qualified path to the configuration file for this deployment
    .Example
        deployAzureService.ps1 -servicename "MyService" -thumbprint "5643060E8F0029FB8C6DB76AAE905C7FA697" -subscriptionid "00000000-0000-0000-0000-000000000000" -slot "Production" -storageservicename "StorageService" -package "C:\deployment\HelloWorld.cspkg" -config "C:\deployments\ServiceConfiguration.cscfg" -label "MyFirstDeployment"
#>
 
param([PARAMETER(Mandatory=$true)][string]$servicename, [PARAMETER(Mandatory=$true)][string]$thumbprint, [PARAMETER(Mandatory=$true)][string]$subscriptionid, [PARAMETER(Mandatory=$true)][string]$slot, [PARAMETER(Mandatory=$true)][string]$storageservicename, [PARAMETER(Mandatory=$true)][string]$package, [PARAMETER(Mandatory=$true)][string]$config, [PARAMETER(Mandatory=$true)][string]$label)
if(!($mgmtsnapin = Get-PSSnapin AzureManagementToolsSnapIn -erroraction silentlycontinue))
{
    Write-Host "Adding ManagementTools SnapIn...please wait"
    Add-PSSnapin AzureManagementToolsSnapIn
    if(!($storagesnapin = Get-PSSnapin AzureCommandletCollectionSnapIn -erroraction silentlycontinue))
    {
        Write-Host "Adding AzureCommandletCollection SnapIn...please wait"
        Add-PSSnapin AzureCommandletCollectionSnapIn
    }
}
$cert = Get-Item cert:\CurrentUser\My\$thumbprint
$service = Get-HostedService $servicename -Certificate $cert -SubscriptionId $subscriptionid
if($service)
{
    $deployment = Get-Deployment -Slot $slot -ServiceName $servicename -SubscriptionId $subscriptionid -Certificate $cert -erroraction silentlycontinue
    $name = $deployment.Name
    if(!$deployment.Name)
    {
        Write-Host "Creating new deployment...please wait"
        New-Deployment -Slot $slot -ServiceName $servicename -SubscriptionId $subscriptionid -Certificate $cert -Package $package -Configuration $config -Label $label -StorageServiceName $storageservicename |
        Get-OperationStatus -WaitToComplete
        
        Write-Host "Starting the new deployment...please wait"
        Get-Deployment -Slot $slot -ServiceName $servicename -SubscriptionId $subscriptionid -Certificate $cert |
        Set-DeploymentStatus "Running" |
        Get-OperationStatus -WaitToComplete
        $storagekeys = Get-StorageKeys -ServiceName $storageservicename -SubscriptionId $subscriptionid -Certificate $cert
        Get-Storage -StorageAccount $storageservicename -SharedKey $storagekeys.Primary | Get-Bloblist -ContainerName mydeployments -ExtensionFilter cspkg | Remove-Blob
    } else
    {
        Write-Host "Service $servicename already has an active deployment with the name $name...please remove the active deployment first"
    }
} else
{
    Write-Host "No service found with the name $servicename"
}

When running from the command line it should produce the following output:

azure_cmdlet

Bookmark Digg Bookmark Del.icio.us Bookmark Facebook Bookmark Reddit Bookmark StumbleUpon Bookmark Yahoo Bookmark Google Bookmark Technorati Bookmark Twitter