Red Gate forums :: View topic - Windows Azure Web Site
Return to www.red-gate.com RSS Feed Available

Search  | Usergroups |  Profile |  Messages |  Log in  Register 
Go to product documentation

Deployment Manager PowerShell Scripts forum

Windows Azure Web Site

Search in Deployment Manager PowerShell Scripts forum
Post new topic   Reply to topic
Jump to:  
Author Message
DavidSimner



Joined: 04 Feb 2010
Posts: 49

PostPosted: Mon Sep 09, 2013 12:00 pm    Post subject: Windows Azure Web Site Reply with quote

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:

#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
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic All times are GMT + 1 Hour
Page 1 of 1

 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group