Windows Azure Web Site

Share your PowerShell scripts for Deployment Manager

Moderators: Mike Upton, justin.caldicott, csmith, chirayu, DavidSimner

Windows Azure Web Site

Postby DavidSimner » Mon Sep 09, 2013 12:00 pm

This is a Deployment Manager Deploy.ps1 PowerShell script to deploy a Windows Azure Web Site.

To use it, you will need to both add some variables in DM, as well as having configured the machine where the DM agent runs, in the user account that the DM agent run as, to have your credentials to the Windows Azure Web Site so that it can stop + start the website.

In more detail, the variables are:
    * RedGateAzureFtpServer
    * RedGateAzureFtpUserName
    * RedGateAzureFtpPassword
The manual setup that you'll need to do on the DM agent for the user account that the agent runs as is:


Then you'll need this in a Deploy.ps1 file in your package:
Code: Select all
#Inputs:
#$RedGateAzureFtpServer = waws-prod-db3-003.ftp.azurewebsites.windows.net
#$RedGateAzureFtpUserName = User01
#$RedGateAzureFtpPassword = ********

# Uploads the contents of the deployed package to the given ftp site, then delete the old files

# This is done by uploading to a temporary file
# checking the upload worked
# and then swap the directories to `deploy` the website
# the finally delete the old wwwroot

$errors = \"\"
if ($null -eq $RedGateAzureFtpServer) {
   $errors = $errors + \", RedGateAzureFtpServer\"
}
if ($null -eq $RedGateAzureFtpUserName) {
   $errors = $errors + \", RedGateAzureFtpUserName\"
}
if ($null -eq $RedGateAzureFtpPassword) {
   $errors = $errors + \", RedGateAzureFtpPassword\"
}

if (0 -ne $errors.length) {
# Throw an error and stop deployment
   Throw ($errors.trim(\", \") + \" must be set to push to ftp site\")
}

$webrootDir = \"site/wwwroot\"
$guid1 = [guid]::NewGuid()
$guid2 = [guid]::NewGuid()
$ftpUrl = \"ftp://$RedGateAzureFtpServer/$webrootDir\"
$ftpTemp1 = \"ftp://$RedGateAzureFtpServer/$guid1\"
$azureWebsite = $RedGateAzureFtpUserName.split('\\')[0]
$ftpTemp2 = \"ftp://$RedGateAzureFtpServer/$guid2\"
$oldWebrootDir = \"/$guid2\"

# Upload the files
Function FtpUpload ([string]$webroot, [string]$localdirectory)
{
   cd $localdirectory
   $files = Get-ChildItem -recurse

   FTPCreateFolder (New-Object System.Uri($webroot))

   foreach($file in $files)
   {
      #Ignore the nuget package used for deployment
      if ($file.Name -eq \"$RedGatePackageNameAndVersion.nupkg\") {
         continue
      }
   
       $uri = New-Object System.Uri($webroot + $file.FullName.Replace($localdirectory,\"\"))
      
       # if a folder
       if( $file.DirectoryName -eq $null)
       {
           Write-Host \"Create folder, URI: $uri\"
           FtpCreateFolder $uri
       }
       else
       {
           Write-Host \"Upload file, URI: $uri, File: \" + $file.FullName
           FtpUploadFile $uri $file.FullName
       }
   }
}

Function FtpUploadFile ([System.Uri]$uri, [string]$filePath)
{
    $ftp = [System.Net.FtpWebRequest]::Create($uri)
    $ftp.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile
    $ftp.Credentials = new-object System.Net.NetworkCredential($RedGateAzureFtpUserName,$RedGateAzureFtpPassword)
    $ftp.UseBinary = $true
    $ftp.UsePassive = $true
    $content = [System.IO.File]::ReadAllBytes($filePath)
    $ftp.ContentLength = $content.Length
    $rs = $ftp.GetRequestStream()
    $rs.Write($content, 0, $content.Length)
    $rs.Close()
    $rs.Dispose()
}

Function FtpCreateFolder ([System.Uri]$uri)
{
    $ftp = [System.Net.FtpWebRequest]::Create($uri)
    $ftp.Method = [System.Net.WebRequestMethods+Ftp]::MakeDirectory
    $ftp.Credentials = new-object System.Net.NetworkCredential($RedGateAzureFtpUserName,$RedGateAzureFtpPassword)
    try
    {
        $rs = $ftp.GetResponse()
    }
    catch [System.Exception]
    {
    }
    if( $rs -ne $null )
    {
        $rs.Close()
    }
}

# Reads the entire stream in one go and return it
# instead of reading stream line by line
Function Receive-Stream ([System.IO.Stream]$reader)
{
   $encoding = [System.Text.Encoding]::GetEncoding( $null )
   $output = \"\"
   [byte[]]$buffer = new-object byte[] 4096
   [int]$total = [int]$count = 0
   do
   {
      $count = $reader.Read($buffer, 0, $buffer.Length)
      $output += $encoding.GetString($buffer, 0, $count)
   } while ($count -gt 0)
 
   $reader.Close()
   $output
}

# Delete the directory $path
# Start by recursively deleting files inside
# then remove the directory itself
Function FtpDelete ([string]$path)
{
   $itemsOnFTPtoDelete = New-Object System.Collections.ArrayList
   
   $uri = New-Object System.Uri($path)
    $ftp = [System.Net.FtpWebRequest]::Create($uri)
    $ftp.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectoryDetails
    $ftp.Credentials = new-object System.Net.NetworkCredential($RedGateAzureFtpUserName,$RedGateAzureFtpPassword)
   
   try
   {
      $rs = $ftp.GetResponse()
      $cache = (Receive-Stream $rs.GetResponseStream())
      
      # Split up the cache into a useable format with an item on each line
      $list = $cache -replace \"(?:.|\\n)*<PRE>\\s+((?:.*|\\n)+)\\s+</PRE>(?:.|\\n)*\",'$1' -split \"`n\"

      # Convert the list of items into a useable format
      foreach($line in $list) {
         $null, $null, [string]$length, $name = $line -split '\\s+'
         $name = ($name -join \" \")
         
         if ($name.Length -eq 0) {
            continue
         }

         $ftpItem = New-Object PSObject -Property @{
            FullName      = $path.trim().trim('/') + '/' + $name
            Type          = $(if($length -eq (($length -as [int]) -as [string])) { \"File\" } else { $length })
         }
      
         [void]$itemsOnFTPtoDelete.Add($ftpItem)
         }

      $rs.Close()
      
      # Delete each file, recursively deleting directories
      foreach ($item in $itemsOnFTPtoDelete) {
         $uri = New-Object System.Uri($item.FullName)
         if (\"<DIR>\" -ne $item.Type) {
            FtpDeleteFile $uri
         } else {
            FtpDelete $item.FullName
         }
      }
      FtpDeleteEmptyDirectory (New-Object System.Uri($path))
   }
   catch
   {
   }
}

Function FtpDeleteFile ([System.Uri]$uri)
{
   Write-Host \"Deleting $uri\"
    $ftp = [System.Net.FtpWebRequest]::Create($uri)
    $ftp.Method = [System.Net.WebRequestMethods+Ftp]::DeleteFile
    $ftp.Credentials = new-object System.Net.NetworkCredential($RedGateAzureFtpUserName,$frpPassword)
   
    try
    {
        $rs = $ftp.GetResponse()
    }
    catch [System.Exception]
    {
    }
    if( $rs -ne $null )
    {
        $rs.Close()
    }
}

Function FtpDeleteEmptyDirectory ([System.Uri]$uri)
{
   Write-Host \"Deleting directory $uri\"
    $ftp = [System.Net.FtpWebRequest]::Create($uri)
    $ftp = [System.Net.FtpWebRequest]$ftp
    $ftp.Method = [System.Net.WebRequestMethods+Ftp]::RemoveDirectory
    $ftp.Credentials = new-object System.Net.NetworkCredential($RedGateAzureFtpUserName,$RedGateAzureFtpPassword)
   
    try
    {
        $rs = $ftp.GetResponse()
    }
    catch [System.Exception]
    {
    }
    if( $rs -ne $null )
    {
        $rs.Close()
    }
}

Function FtpRename ([System.Uri]$uri, [string]$newname)
{
   Write-Host \"Renaming $uri to $newname\"
    $ftp = [System.Net.FtpWebRequest]::Create($uri)
    $ftp.Method = [System.Net.WebRequestMethods+Ftp]::Rename
    $ftp.Credentials = new-object System.Net.NetworkCredential($RedGateAzureFtpUserName,$RedGateAzureFtpPassword)
   $ftp.RenameTo = $newname
   
    try
    {
        $rs = $ftp.GetResponse()
    }
    catch [System.Exception]
    {
    }
    if( $rs -ne $null )
    {
        $rs.Close()
    }
}

# Checks the files in $webroot versus $localdirectory
# recursively called for directories
Function FtpValidate ([string]$webroot, [string]$localdirectory)
{
   Write-Host \"Validating directory $localdirectory was uploaded\"
   $itemsOnFTP = New-Object System.Collections.ArrayList
   cd $localdirectory
   $uploadedFiles = Get-ChildItem
   
   $uri = New-Object System.Uri($webroot)
    $ftp = [System.Net.FtpWebRequest]::Create($uri)
    $ftp.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectoryDetails
    $ftp.Credentials = new-object System.Net.NetworkCredential($RedGateAzureFtpUserName,$RedGateAzureFtpPassword)
   
   try
   {
      # Get the items stored on the ftp at the webroot location
      $rs = $ftp.GetResponse()
      $cache = (Receive-Stream $rs.GetResponseStream())
      
      $list = $cache -replace \"(?:.|\\n)*<PRE>\\s+((?:.*|\\n)+)\\s+</PRE>(?:.|\\n)*\",'$1' -split \"`n\"

      foreach($line in $list) {
         $null, $null, [string]$length, $name = $line -split '\\s+'
         $name = ($name -join \" \").Trim()
         
         if ($name.Length -eq 0) {
            continue
         }

         $ftpItem = New-Object PSObject -Property @{
            Name        = $name
            FullName      = $webroot.trim().trim('/') + '/' + $name
            Length        = $(if($length -eq (($length -as [int]) -as [string])) { [int]$length } else { $null })
            Type          = $(if($length -eq (($length -as [int]) -as [string])) { \"File\" } else { $length })
         }
         
         [void]$itemsOnFTP.Add($ftpItem)
         }

      $rs.Close()
   } catch {}
   foreach ($file in $uploadedFiles) {
      # ignore the package used for deployment
      if ($file.Name -eq \"$RedGatePackageNameAndVersion.nupkg\") {
         continue
      }
      # Check each item has been uploaded correctly
      
      Write-Host \"Validating item: $file\"
      
      $found = $null
      foreach ($ftpItem in $itemsOnFTP) {
         if ($ftpItem.Name -eq $file.Name) { $found = $ftpItem }
      }
      # If it doesn't exist on ftp then error
      if ($found -eq $null) {
         throw \"$file failed to uploaded\"
      }
      
       # if a folder
       if( $file.DirectoryName -eq $null)
       {
         # check the internals are the same
           FtpValidate $found.FullName $file.FullName
       } else {
         # check the file lengths are equal
         if ($found.Length -ne $file.Length) {
            throw \"$file was not uploaded correctly\"
         }
      }
   }
}

$myDir = Split-Path -Parent $MyInvocation.MyCommand.Path
Write-Host \"Uploading new files\"
FtpUpload $ftpTemp1 $myDir
Write-Host \"Validating upload\"
FtpValidate $ftpTemp1 $myDir
Write-Host \"Validation Successful\"
Write-Host \"Swapping to new website\"
Stop-AzureWebsite $azureWebsite
FtpRename (New-Object System.Uri($ftpUrl)) $oldWebrootDir
FtpRename (New-Object System.Uri($ftpTemp1)) $webrootDir
Start-AzureWebsite $azureWebsite
Write-Host \"Delete old files\"
FtpDelete $ftpTemp2
DavidSimner
 
Posts: 49
Joined: Thu Feb 04, 2010 6:05 pm

Return to Deployment Manager PowerShell Scripts

Who is online

Users browsing this forum: No registered users and 0 guests