HOT for IIS with Drupal

It deploys a new Drupal 7 web site on a server with IIS
and PHP 5.4 configured. Web site uses a local database on
SQL Server 2008 R2 SP2 Express

Required tools are downloaded from the internet using
official links. SHA1 hashes are computed for the downloaded files
and compared with the expected hashes to ensure file integrity.

The unit tests for the user data scripts are written using
Pester 3.0

Change-Id: Ia9c12db0a92fc4f39be9056c67471eb8c136a86a
Partially-Implements: blueprint windows-instances
This commit is contained in:
Ionut-Madalin Balutoiu 2014-09-09 23:02:17 +03:00
parent 063e6a0930
commit 1068c8fe1a
5 changed files with 1495 additions and 0 deletions

View File

@ -0,0 +1,390 @@
<#
Copyright 2014 Cloudbase Solutions Srl
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
#>
$rebotCode = 1001
$reexecuteCode = 1002
$rebootAndReexecuteCode = 1003
function ExitFrom-Script {
param(
[int]$ExitCode
)
exit $ExitCode
}
function ExecuteWith-Retry {
param(
[ScriptBlock]$Command,
[int]$MaxRetryCount=10,
[int]$RetryInterval=3,
[array]$Arguments=@()
)
$currentErrorActionPreference = $ErrorActionPreference
$ErrorActionPreference = "Continue"
$retryCount = 0
while ($true) {
try {
$res = Invoke-Command -ScriptBlock $Command `
-ArgumentList $Arguments
$ErrorActionPreference = $currentErrorActionPreference
return $res
} catch [System.Exception] {
$retryCount++
if ($retryCount -gt $MaxRetryCount) {
$ErrorActionPreference = $currentErrorActionPreference
throw $_.Exception
} else {
Write-Error $_.Exception
Start-Sleep $RetryInterval
}
}
}
}
function Execute-Command {
param(
[ScriptBlock]$Command,
[array]$Arguments=@(),
[string]$ErrorMessage
)
$res = Invoke-Command -ScriptBlock $Command -ArgumentList $Arguments
if ($LASTEXITCODE -ne 0) {
throw $ErrorMessage
}
return $res
}
function Is-WindowsServer2008R2 () {
$winVer = (Get-WmiObject -class Win32_OperatingSystem).Version.Split('.')
return (($winVer[0] -eq 6) -and ($winVer[1] -eq 1))
}
function Get-PSMajorVersion () {
return $PSVersionTable.PSVersion.Major
}
function Install-WindowsFeatures {
param(
[Parameter(Mandatory=$true)]
[array]$Features,
[int]$RebootCode=$rebootAndReexecuteCode
)
if ((Is-WindowsServer2008R2) -eq $true) {
Import-Module ServerManager
}
$rebootNeeded = $false
foreach ($feature in $Features) {
if ((Is-WindowsServer2008R2) -eq $true) {
$state = ExecuteWith-Retry -Command {
Add-WindowsFeature -Name $feature -ErrorAction Stop
}
} else {
$state = ExecuteWith-Retry -Command {
Install-WindowsFeature -Name $feature -ErrorAction Stop
}
}
if ($state.Success -eq $true) {
if ($state.RestartNeeded -eq 'Yes') {
$rebootNeeded = $true
}
} else {
throw "Install failed for feature $feature"
}
}
if ($rebootNeeded -eq $true) {
ExitFrom-Script $RebootCode
}
}
function Unzip-File {
param(
[Parameter(Mandatory=$true)]
[string]$ZipFile,
[Parameter(Mandatory=$true)]
[string]$Destination,
[string]$7zPath = "${env:ProgramFiles(x86)}\7-Zip\7z.exe"
)
$res = Execute-Command -Command {
& $7zPath x "-o$Destination" $ZipFile
}
return $res
}
function Download-File {
param(
[Parameter(Mandatory=$true)]
[string]$DownloadLink,
[Parameter(Mandatory=$true)]
[string]$DestinationFile
)
$webclient = New-Object System.Net.WebClient
ExecuteWith-Retry -Command {
$webclient.DownloadFile($DownloadLink, $DestinationFile)
}
}
# Get-FileHash for Powershell versions less than 4.0 (SHA1 algorithm only)
function Get-FileSHA1Hash {
[CmdletBinding()]
param(
[parameter(Mandatory=$true)]
[string]$Path,
[string]$Algorithm = "SHA1"
)
process
{
if ($Algorithm -ne "SHA1") {
throw "Unsupported algorithm: $Algorithm"
}
$fullPath = Resolve-Path $Path
$f = [System.IO.File]::OpenRead($fullPath)
$sham = $null
try {
$sham = New-Object System.Security.Cryptography.SHA1Managed
$hash = $sham.ComputeHash($f)
$hashSB = New-Object System.Text.StringBuilder `
-ArgumentList ($hash.Length * 2)
foreach ($b in $hash) {
$sb = $hashSB.AppendFormat("{0:x2}", $b)
}
return [PSCustomObject]@{ Algorithm="SHA1";
Hash=$hashSB.ToString().ToUpper();
Path=$fullPath }
}
finally {
$f.Close()
if($sham) {
$sham.Clear()
}
}
}
}
function Check-FileIntegrityWithSHA1 {
param(
[Parameter(Mandatory=$true)]
[string]$File,
[Parameter(Mandatory=$true)]
[string]$ExpectedSHA1Hash
)
if ((Get-PSMajorVersion) -lt 4) {
$hash = (Get-FileSHA1Hash -Path $File).Hash
} else {
$hash = (Get-FileHash -Path $File -Algorithm "SHA1").Hash
}
if ($hash -ne $ExpectedSHA1Hash) {
$errMsg = "SHA1 hash not valid for file: $filename. " +
"Expected: $ExpectedSHA1Hash Current: $hash"
throw $errMsg
}
}
function Install-Program {
param(
[Parameter(Mandatory=$true)]
[string]$DownloadLink,
[Parameter(Mandatory=$true)]
[string]$DestinationFile,
[Parameter(Mandatory=$true)]
[string]$ExpectedSHA1Hash,
[Parameter(Mandatory=$true)]
[array]$Arguments,
[Parameter(Mandatory=$true)]
[string]$ErrorMessage
)
Download-File $DownloadLink $DestinationFile
Check-FileIntegrityWithSHA1 $DestinationFile $ExpectedSHA1Hash
$p = Start-Process -FilePath $DestinationFile `
-ArgumentList $Arguments `
-PassThru `
-Wait
if ($p.ExitCode -ne 0) {
throw $ErrorMessage
}
Remove-Item $DestinationFile
}
function Set-IniFileValue {
[CmdletBinding()]
param(
[parameter(Mandatory=$true, ValueFromPipeline=$true)]
[string]$Key,
[parameter()]
[string]$Section = "DEFAULT",
[parameter(Mandatory=$true)]
[string]$Value,
[parameter(Mandatory=$true)]
[string]$Path
)
process
{
$Source = @"
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace PSCloudbase
{
public sealed class Win32IniApi
{
[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern uint GetPrivateProfileString(
string lpAppName,
string lpKeyName,
string lpDefault,
StringBuilder lpReturnedString,
uint nSize,
string lpFileName);
[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WritePrivateProfileString(
string lpAppName,
string lpKeyName,
StringBuilder lpString, // Don't use string, as Powershell replaces $null with an empty string
string lpFileName);
[DllImport("Kernel32.dll")]
public static extern uint GetLastError();
}
}
"@
Add-Type -TypeDefinition $Source -Language CSharp
$retVal = [PSCloudbase.Win32IniApi]::WritePrivateProfileString($Section, $Key, $Value, $Path)
if (!$retVal -and [PSCloudbase.Win32IniApi]::GetLastError()) {
throw "Cannot set value in ini file: " + [PSCloudbase.Win32IniApi]::GetLastError()
}
}
}
# Invoke-RestMethod for Powershell versions less than 4.0
function Invoke-RestMethodWrapper {
param(
[Uri]$Uri,
[Object]$Body,
[System.Collections.IDictionary]$Headers,
[string]$Method
)
$request = [System.Net.WebRequest]::Create($Uri)
$request.Method = $Method
foreach ($key in $Headers.Keys) {
try {
$request.Headers.Add($key, $Headers[$key])
} catch {
$property = $key.Replace('-', '')
$request.$property = $Headers[$key]
}
}
if (($Body -ne $null) -and ($Method -eq "POST")) {
$encoding = [System.Text.Encoding]::GetEncoding("iso-8859-1")
$bytes = $encoding.GetBytes($Body)
$request.ContentLength = $bytes.Length
$writeStream = $request.GetRequestStream()
$writeStream.Write($bytes, 0, $bytes.Length)
}
$response = $request.GetResponse()
$requestStream = $response.GetResponseStream()
$readStream = New-Object System.IO.StreamReader $requestStream
$data = $readStream.ReadToEnd()
return $data
}
function Invoke-HeatRestMethod {
param(
[Uri]$Endpoint,
[System.String]$HeatMessageJSON,
[System.Collections.IDictionary]$Headers
)
if ((Get-PSMajorVersion) -lt 4) {
$result = Invoke-RestMethodWrapper -Method "POST" `
-Uri $Endpoint `
-Body $HeatMessageJSON `
-Headers $Headers
} else {
$result = Invoke-RestMethod -Method "POST" `
-Uri $Endpoint `
-Body $HeatMessageJSON `
-Headers $Headers
}
}
function Send-HeatWaitSignal {
param(
[parameter(Mandatory=$true)]
[string]$Endpoint,
[parameter(Mandatory=$true)]
[string]$Token,
$Message,
$Success=$true
)
$statusMap = @{
$true="SUCCESS";
$false="FAILURE"
}
$status = $statusMap[$Success]
$heatMessageJSON =
"{
`"status`": `"$status`",
`"reason`": `"Configuration script has been executed.`",
`"data`": `"$Message`"
}"
$headers = @{
"X-Auth-Token"=$Token;
"Accept"="application/json";
"Content-Type"= "application/json";
}
Invoke-HeatRestMethod -Endpoint $Endpoint `
-HeatMessageJSON $heatMessageJSON `
-Headers $headers
}
function LogTo-File {
param(
$LogMessage,
$LogFile="C:\cfn\userdata.log",
$Topic="General"
)
$date = Get-Date
$fullMessage = "$date | $Topic | $LogMessage"
Add-Content -Path $LogFile -Value $fullMessage
}
Export-ModuleMember -Function *

View File

@ -0,0 +1,36 @@
#ps1_sysnative
<#
Copyright 2014 Cloudbase Solutions Srl
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
#>
$ErrorActionPreference = 'Stop'
$cfnFolder = Join-Path $env:SystemDrive "cfn"
$moduleName = "IIS_Drupal.psm1"
$modulePath = Join-Path $cfnFolder $moduleName
Import-Module -Name $modulePath -DisableNameChecking
$parameters = @{
'ENDPOINT' = 'wait_handle_endpoint';
'TOKEN' = 'wait_handle_token';
'SA_PASS' = 'sa_password';
'ADMIN_USER' = 'admin_username';
'ADMIN_PASS' = 'admin_password';
'ADMIN_EMAIL' = 'admin_email';
'SITE_NAME' = 'website_name'
}
Initialize-Server $parameters

View File

@ -0,0 +1,416 @@
<#
Copyright 2014 Cloudbase Solutions Srl
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
#>
$cfnFolder = Join-Path $env:SystemDrive "cfn"
$moduleName = "heat-powershell-utils.psm1"
$modulePath = Join-Path $cfnFolder $moduleName
Import-Module -Name $modulePath `
-DisableNameChecking `
-ErrorAction SilentlyContinue
# In case download links change or become unavailable,
# they must be updated and new expected SHA1 hashes must be computed.
$downloadLinks = @{
'SQLEXPRESS08' = 'http://download.microsoft.com/download/0/4/B/04BE03CD-EAF3-4797-9D8D-2E08E316C998/SQLEXPR_x64_ENU.exe';
'SQLDRIVERS' = 'http://download.microsoft.com/download/C/D/B/CDB0A3BB-600E-42ED-8D5E-E4630C905371/SQLSRV30.EXE';
'PHP54' = 'http://windows.php.net/downloads/releases/php-5.4.33-nts-Win32-VC9-x86.zip';
'VC2008SP1' = 'http://download.microsoft.com/download/d/d/9/dd9a82d0-52ef-40db-8dab-795376989c03/vcredist_x86.exe';
'UR20' = 'http://download.microsoft.com/download/6/7/D/67D80164-7DD0-48AF-86E3-DE7A182D6815/rewrite_2.0_rtw_x64.msi';
'DRUSH' = 'http://www.drush.org/sites/default/files/attachments/Drush-6.0-2013-08-28-Installer-v1.0.21.msi';
'DRUPALDRIVERS' = 'http://ftp.drupal.org/files/projects/sqlsrv-7.x-1.x-dev.zip';
'DRUPAL' = 'http://ftp.drupal.org/files/projects/drupal-7.31.zip';
'SQLNCLI12' = 'http://download.microsoft.com/download/4/B/1/4B1E9B0E-A4F3-4715-B417-31C82302A70A/ENU/x64/sqlncli.msi';
'7Z' = 'http://softlayer-ams.dl.sourceforge.net/project/sevenzip/7-Zip/9.20/7z920.msi'
}
$sha1Hashes = @{
'SQLEXPRESS08' = 'E768A3B70E3F3B596EFFA9F57D812F95C0A0506B';
'SQLDRIVERS' = '1457A9F9B87119265966EEE6C9A648249A7A83E0';
'PHP54' = 'F414F9CC3585CBE511E6C183261F347BAE071784';
'VC2008SP1' = '6939100E397CEF26EC22E95E53FCD9FC979B7BC9';
'UR20' = '84BDEAEF26BCB2CB60BB8686EAF6194607F7F003';
'DRUSH' = 'CA71B7AFAAF18904B23DDB9224E030C97978AC89';
'DRUPALDRIVERS' = '6B96C56CD3800F5B203D5DEF9AB5814629FCBCAB';
'DRUPAL' = '2C41B3BF4C7819F3531E1DEBDCD14DAD74A532D9';
'SQLNCLI12' = '789CD5F898F80A799F0288F140F3FBCDF0473DE8';
'7Z' = 'C67D3F611EA3EB3336CF92F6FFCAFDB14F8B12AF'
}
function Install-IIS () {
LogTo-File "Install IIS windows features"
Install-WindowsFeatures `
-Features @("Web-Server",
"Web-Http-Redirect",
"Web-DAV-Publishing",
"Web-Custom-Logging",
"Web-Log-Libraries",
"Web-ODBC-Logging",
"Web-Request-Monitor",
"Web-Http-Tracing",
"Web-Mgmt-Console",
"Web-Scripting-Tools",
"Web-Mgmt-Service",
"Web-CGI",
"NET-Framework-Core")
}
function Install-SQLServerExpress2008R2SP2 ($SAPassword) {
LogTo-File "Install SQL Server Express 2008 R2 SP2"
$file = Join-Path $env:TEMP $downloadLinks['SQLEXPRESS08'].Split('/')[-1]
Install-Program `
-DownloadLink $downloadLinks['SQLEXPRESS08'] `
-DestinationFile $file `
-ExpectedSHA1Hash $sha1Hashes['SQLEXPRESS08'] `
-Arguments @('/ACTION=Install',
'/Q',
'/IACCEPTSQLSERVERLICENSETERMS',
'/INSTANCENAME=SQLEXPRESS',
'/SECURITYMODE=SQL',
"/SAPWD=$SAPassword",
'/SQLSYSADMINACCOUNTS="BUILTIN\Administrators"') `
-ErrorMessage "Failed to install SQL Server 2008 R2 SP2 Express"
$sqlEnvPath =
";${env:ProgramFiles(x86)}\Microsoft SQL Server\100\Tools\Binn\" +
";$env:ProgramFiles\Microsoft SQL Server\100\Tools\Binn\" +
";$env:ProgramFiles\Microsoft SQL Server\100\DTS\Binn\"
$env:Path += $sqlEnvPath
}
function Install-SevenZip () {
LogTo-File "Install 7-Zip"
$file = Join-Path $env:TEMP $downloadLinks['7Z'].Split('/')[-1]
Install-Program `
-DownloadLink $downloadLinks['7Z'] `
-DestinationFile $file `
-ExpectedSHA1Hash $sha1Hashes['7Z'] `
-Arguments @("/Q") `
-ErrorMessage "Failed to install 7-Zip 9.20"
}
function Install-SQLServerDriversForPHP ($ExtLocation) {
LogTo-File "Install SQL Server drivers for PHP"
$SQLDriversPath = Join-Path $env:TEMP "SQLDrivers"
$file = Join-Path $env:TEMP $downloadLinks['SQLDRIVERS'].Split('/')[-1]
Install-Program `
-DownloadLink $downloadLinks['SQLDRIVERS'] `
-DestinationFile $file `
-ExpectedSHA1Hash $sha1Hashes['SQLDRIVERS'] `
-Arguments @("/Q",
"/T:$SQLDriversPath",
"/C") `
-ErrorMessage "Failed to extract drivers into the specified path"
$sqlsrv = Join-Path $SQLDriversPath "php_sqlsrv_54_nts.dll"
$sqlsrvPDO = Join-Path $SQLDriversPath "php_pdo_sqlsrv_54_nts.dll"
Copy-Item $sqlsrv $ExtLocation
Copy-Item $sqlsrvPDO $ExtLocation
Remove-Item $SQLDriversPath -Recurse
}
function Add-PHPSettings ($Settings, $SectionName="DEFAULT", $IniPath) {
foreach ($key in $Settings.Keys) {
Set-IniFileValue -Path $IniPath `
-Section $SectionName `
-Key $key `
-Value $Settings[$key]
}
}
function Enable-PHPExtensions ($Extensions, $IniPath) {
foreach ($key in $Extensions.Keys) {
Set-IniFileValue -Path $IniPath `
-Section $key `
-Key "extension" `
-Value $Extensions[$key]
}
}
function Configure-PHP54 ($PHPLocation, $ExtLocation) {
LogTo-File "Configure PHP for IIS"
$PHPIni = Join-Path $PHPLocation "php.ini"
$oldPHPIni = Join-Path $PHPLocation "php.ini-production"
Copy-Item $oldPhpIni $PHPIni
Set-IniFileValue -Path $PHPIni `
-Section "PHP" `
-Key "memory_limit" `
-Value "128M"
$settings = @{
"error_log" = "$env:SystemRoot\temp\PHP_errors.log";
"upload_tmp_dir" = "$env:SystemRoot\temp";
"session.save_path" = "$env:SystemRoot\temp";
"cgi.force_redirect" = 0;
"cgi.fix_pathinfo" = 1;
"fastcgi.impersonate" = 1;
"fastcgi.logging" = 0;
"max_execution_time" = 300;
"extension_dir" = $ExtLocation }
Add-PHPSettings -Settings $settings `
-IniPath $PHPIni
$extensions = @{
'MYSQL' = 'php_mysql.dll';
'MYSQLI' = 'php_mysqli.dll';
'SQLSRV_54_NTS' = 'php_sqlsrv_54_nts.dll';
'MBSTRING' = 'php_mbstring.dll';
'GD2' = 'php_gd2.dll';
'GETTEXT' = 'php_gettext.dll';
'CURL' = 'php_curl.dll';
'EXIF' = 'php_exif.dll';
'XMLRPC' = 'php_xmlrpc.dll';
'OPENSSL' = 'php_openssl.dll';
'SOAP' = 'php_soap.dll';
'PDO_MYSQL' = 'php_pdo_mysql.dll';
'PDO_SQLITE' = 'php_pdo_sqlite.dll';
'PDO_SQLSRV_54_NTS' = 'php_pdo_sqlsrv_54_nts.dll';
'IMAP' = 'php_imap.dll';
'TIDY' = 'php_tidy.dll'}
Enable-PHPExtensions -Extensions $extensions `
-IniPath $PHPIni
$appcmd = Join-Path $env:SystemRoot "system32\inetsrv\appcmd.exe"
Execute-Command -Command {
& $appcmd set config /section:system.webServer/fastCGI `
/+"[fullPath='$PHPLocation\php-cgi.exe']"
} -ErrorMessage "Error occured while creating FastCGI IIS process pool"
Execute-Command -Command {
& $appcmd set config /section:system.webServer/handlers `
/+"[name='PHP_via_FastCGI', `
path='*.php', `
verb='*', `
modules='FastCgiModule', `
scriptProcessor='$PHPLocation\php-cgi.exe', `
resourceType='Either']"
} -ErrorMessage "Failed to create IIS handler mapping for PHP requests"
Execute-Command -Command {
& $appcmd set config -section:system.webServer/fastCgi `
"/[fullPath='$PHPLocation\php-cgi.exe'].instanceMaxRequests:10000"
} -ErrorMessage "Failed to set php-cgi InstanceMaxRequests"
Execute-Command -Command {
$cmd = "[fullPath='$PHPLocation\php-cgi.exe'].environmentVariables." +
"[name='PHP_FCGI_MAX_REQUESTS',value='10000']"
& $appcmd set config -section:system.webServer/fastCgi /+$cmd
} -ErrorMessage "Failed to set PHP_FCGI_MAX_REQUESTS environment variable"
}
function Install-PHP54 ($PHPLocation) {
LogTo-File "Install PHP 5.4"
New-Item -ItemType Directory -Path $PHPLocation
$phpZip = Join-Path $env:TEMP $downloadLinks['PHP54'].Split('/')[-1]
Download-File $downloadLinks['PHP54'] $phpZip
Check-FileIntegrityWithSHA1 $phpZip $sha1Hashes['PHP54']
Unzip-File $phpZip $PHPLocation
Remove-Item -Path $phpZip
$extLocation = Join-Path $PHPLocation "ext"
Install-SQLServerDriversForPHP -ExtLocation $extLocation
Configure-PHP54 -PHPLocation $PHPLocation `
-ExtLocation $extLocation
}
function Install-Drupal7 {
param(
[string]$SAPassword,
[string]$AdminUsername,
[string]$AdminPassword,
[string]$AdminEmail,
[string]$WebsiteName
)
LogTo-File "Install Drupal 7"
$file = Join-Path $env:TEMP $downloadLinks['VC2008SP1'].Split('/')[-1]
Install-Program `
-DownloadLink $downloadLinks['VC2008SP1'] `
-DestinationFile $file `
-ExpectedSHA1Hash $sha1Hashes['VC2008SP1'] `
-Arguments "/q" `
-ErrorMessage "Microsoft Visual C++ 2008 SP1 failed to install"
$file = Join-Path $env:TEMP $downloadLinks['UR20'].Split('/')[-1]
Install-Program `
-DownloadLink $downloadLinks['UR20'] `
-DestinationFile $file `
-ExpectedSHA1Hash $sha1Hashes['UR20'] `
-Arguments "/q" `
-ErrorMessage "URL Rewrite 2.0 failed to install"
$file = Join-Path $env:TEMP $downloadLinks['SQLNCLI12'].Split('/')[-1]
Install-Program `
-DownloadLink $downloadLinks['SQLNCLI12'] `
-DestinationFile $file `
-ExpectedSHA1Hash $sha1Hashes['SQLNCLI12'] `
-Arguments @("/q",
"ADDLOCAL=ALL",
"IACCEPTSQLNCLILICENSETERMS=YES") `
-ErrorMessage "SQL Server 2012 Native Client failed to install"
$drupalVer = $downloadLinks['DRUPAL'].Split('/')[-1].Trim('.zip')
$drupalZip = Join-Path $env:TEMP ($drupalVer + ".zip")
Download-File $downloadLinks['DRUPAL'] $drupalZip
Check-FileIntegrityWithSHA1 $drupalZip $sha1Hashes['DRUPAL']
Unzip-File $drupalZip $env:TEMP
$drupal7 = Join-Path $env:SystemDrive "inetpub\wwwroot\drupal7"
New-Item -ItemType Directory -Path $drupal7
$drupalTemp = Join-Path $env:TEMP $drupalVer
Copy-Item "$drupalTemp\*" $drupal7 -Recurse
Remove-Item $drupalTemp -Recurse
Remove-Item $drupalZip
$defaultPath = Join-Path $drupal7 "sites\default"
$oldSettings = Join-Path $defaultPath "default.settings.php"
$settings = Join-Path $defaultPath "settings.php"
Copy-Item $oldSettings $settings
$sqlDriversZip = Join-Path $env:TEMP `
$downloadLinks['DRUPALDRIVERS'].Split('/')[-1]
Download-File $downloadLinks['DRUPALDRIVERS'] $sqlDriversZip
Check-FileIntegrityWithSHA1 $sqlDriversZip $sha1Hashes['DRUPALDRIVERS']
Unzip-File $sqlDriversZip "$drupal7\sites\all\modules"
Copy-Item "$drupal7\sites\all\modules\sqlsrv\sqlsrv" `
"$drupal7\includes\database" -Recurse
Remove-Item $sqlDriversZip
$appcmd = Join-Path $env:SystemRoot "system32\inetsrv\appcmd.exe"
Execute-Command -Command {
& $appCmd delete site 'Default Web Site'
} -ErrorMessage "Failed to delete default web site"
Execute-Command -Command {
& $appCmd add site /site.name:'Drupal7' `
/+"bindings.[protocol='http', bindingInformation='*:80:']" `
/physicalPath:"$drupal7"
} -ErrorMessage "Failed to create Drupal web site"
Execute-Command -Command {
& $appcmd add apppool /name:'Drupal7' /managedRuntimeVersion:'' `
/managedPipelineMode:Integrated
} -ErrorMessage "Failed to create Drupal application pool"
Execute-Command -Command {
& $appCmd set site /site.name:'Drupal7' `
/"[path='/']".applicationPool:'Drupal7'
} -ErrorMessage "Failed to assign website to Drupal application pool"
Execute-Command -Command {
icacls.exe $defaultPath /grant "IUSR:(OI)(CI)(M)"
} -ErrorMessage "Failed to set permissions"
Execute-Command -Command {
iisreset.exe /restart
} -ErrorMessage "Failed to restart IIS server"
LogTo-File "Create Drupal database"
$query = "USE [master]
GO
CREATE DATABASE drupal
GO"
Execute-Command -Command {
SQLCMD.EXE -S '.\SQLEXPRESS' -Q $query
} -ErrorMessage "Failed to create Drupal database and user"
$file = Join-Path $env:TEMP $downloadLinks['DRUSH'].Split('/')[-1]
Install-Program `
-DownloadLink $downloadLinks['DRUSH'] `
-DestinationFile $file `
-ExpectedSHA1Hash $sha1Hashes['DRUSH'] `
-Arguments "/q" `
-ErrorMessage "Drush failed to install"
$drushEnvPath = ";$env:ProgramData\Drush\" +
";${env:ProgramFiles(x86)}\Drush\GnuWin32\bin" +
";${env:ProgramFiles(x86)}\Drush\Php"
$env:Path += $drushEnvPath
LogTo-File "Start configure Drupal website with Drush"
Push-Location $drupal7
$drush = Join-Path $env:ProgramData "Drush\drush.bat"
$dbUrl = "sqlsrv://sa`:$SAPassword@.\SQLEXPRESS/drupal"
Execute-Command -Command {
& $drush site-install standard `
--db-url=$dbUrl `
--account-mail=$AdminEmail `
--account-name=$AdminUsername `
--account-pass=$AdminPassword `
--site-name="$WebsiteName" `
--site-mail=$AdminEmail `
--y
} -ErrorMessage "Failed to configure Drupal site with drush"
$tempFolder = Join-Path $defaultPath "files\tmp"
New-Item -ItemType Directory -Path $tempFolder
Execute-Command -Command {
& $drush vset file_temporary_path $tempFolder
} -ErrorMessage "Failed to set Drupal temporary folder"
Pop-Location
}
function Install-IISWithDrupal ($parameters) {
$PHPLocation = Join-Path $env:SystemDrive "PHP\PHP54"
Install-IIS
Install-SQLServerExpress2008R2SP2 -SAPassword $parameters['SA_PASS']
Install-SevenZip
Install-PHP54 -PHPLocation $PHPLocation
Install-Drupal7 -SAPassword $parameters['SA_PASS'] `
-AdminUsername $parameters['ADMIN_USER'] `
-AdminPassword $parameters['ADMIN_PASS'] `
-AdminEmail $parameters['ADMIN_EMAIL'] `
-WebsiteName $parameters['SITE_NAME']
}
function Initialize-Server ($parameters) {
try {
LogTo-File "IIS with Drupal installation started"
Install-IISWithDrupal $parameters
$successMessage = "Finished IIS with Drupal installation"
LogTo-File $successMessage
Send-HeatWaitSignal -Endpoint $parameters['ENDPOINT'] `
-Message $successMessage `
-Success $true `
-Token $parameters['TOKEN']
} catch {
$failMessage = "IIS with Drupal installation encountered an error"
LogTo-File $failMessage
LogTo-File "Exception details: $_.Exception.Message"
Send-HeatWaitSignal -Endpoint $parameters['ENDPOINT'] `
-Message $_.Exception.Message `
-Success $false `
-Token $parameters['TOKEN']
}
}
Export-ModuleMember -Function Initialize-Server

View File

@ -0,0 +1,186 @@
heat_template_version: 2013-05-23
description: >
It deploys a Drupal web site on Internet Information Services
with PHP configured. It has a local database on SQL Server Express
parameters:
key_name:
type: string
description: Name of an existing key pair used to encrypt Admin password.
flavor:
type: string
description: ID or name of an existing flavor to be used for the instance.
default: m1.small
image:
type: string
description: ID or name of an existing valid Windows Server image.
public_network_id:
type: string
description: >
ID of an existing public network where a floating IP will be allocated.
private_network_id:
type: string
description: ID of an existing private network.
sa_password:
type: string
description: SQL Server Express system administrator password.
hidden: true
constraints:
- length: { min: 8 }
description: SA password must be at least 8 characters long.
- allowed_pattern: '(?=^.{6,255}$)((?=.*\\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))^.*'
description: >
SA password must contain uppercase and lowercase letters, numbers,
non-alphanumeric characters and it must not contain whitespaces.
drupal_admin_username:
type: string
description: Drupal admin user name.
default: cloudbase
constraints:
- length: { min: 4, max: 16 }
description: >
Drupal admin user name must be between 4 and 16 characters long.
- allowed_pattern: '^[a-zA-Z0-9]+$'
description: >
Drupal admin user name must contain only alphanumeric characters.
drupal_admin_password:
type: string
description: Drupal admin user password.
hidden: true
constraints:
- length: { min: 8 }
description: >
Drupal admin user password must be at least 8 characters long.
- allowed_pattern: '^[\S]+$'
description: Drupal admin user password must not contain whitespaces.
drupal_admin_email:
type: string
description: Drupal administrator email.
constraints:
- length: { min: 1 }
description: Drupal admin email must not be empty.
- allowed_pattern: '^[a-zA-Z0-9._%+-]+@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,4}$'
description: Drupal admin email must be a valid email address.
drupal_site_name:
type: string
description: Drupal site name.
default: My Drupal IIS website created with Heat
constraints:
- length: { min: 1 }
description: Drupal site name must not be empty.
- allowed_pattern: '^(?!.*["\r\n\f]).*$'
description: >
Drupal site name must not contain double quotes and any
whitespace character (excepting spaces and tabs).
max_timeout:
type: number
default: 3600
description: >
The maximum allowed time (seconds) for the instalation to finish.
resources:
iis_drupal:
type: OS::Nova::Server
properties:
image: { get_param: image }
flavor: { get_param: flavor }
key_name: { get_param: key_name }
networks:
- port: { get_resource: server_port }
user_data_format: RAW
user_data: { get_resource: iis_drupal_init }
iis_drupal_wait_condition:
type: OS::Heat::WaitCondition
depends_on: iis_drupal_wait_condition_handle
properties:
handle: { get_resource: iis_drupal_wait_condition_handle }
count: 1
timeout: { get_param: max_timeout }
iis_drupal_wait_condition_handle:
type: OS::Heat::WaitConditionHandle
server_port:
type: OS::Neutron::Port
properties:
network_id: { get_param: private_network_id }
server_floating_ip:
type: OS::Neutron::FloatingIP
properties:
floating_network_id: { get_param: public_network_id }
port_id: { get_resource: server_port }
utils_module:
type: OS::Heat::SoftwareConfig
properties:
group: ungrouped
config: { get_file: Common/heat-powershell-utils.psm1 }
iis_drupal_module:
type: OS::Heat::SoftwareConfig
properties:
group: ungrouped
config: { get_file: IIS_Drupal.psm1 }
iis_drupal_main:
type: OS::Heat::SoftwareConfig
properties:
group: ungrouped
config:
str_replace:
template: { get_file: IIS_Drupal.ps1 }
params:
sa_password: { get_param: sa_password }
admin_username: { get_param: drupal_admin_username }
admin_password: { get_param: drupal_admin_password }
admin_email: { get_param: drupal_admin_email }
website_name: { get_param: drupal_site_name }
wait_handle_endpoint:
{ get_attr: [iis_drupal_wait_condition_handle, endpoint] }
wait_handle_token:
{ get_attr: [iis_drupal_wait_condition_handle, token] }
iis_drupal_init:
type: OS::Heat::MultipartMime
properties:
parts:
[
{
filename: "heat-powershell-utils.psm1",
subtype: "x-cfninitdata",
config: { get_resource: utils_module }
},
{
filename: "IIS_Drupal.psm1",
subtype: "x-cfninitdata",
config: { get_resource: iis_drupal_module }
},
{
filename: "cfn-userdata",
subtype: "x-cfninitdata",
config: { get_resource: iis_drupal_main }
}
]
outputs:
drupal_url:
description: URL where you can access the Drupal web site
value:
str_replace:
template: >
URL: http://host
params:
host: { get_attr: [ server_floating_ip, floating_ip_address ] }

View File

@ -0,0 +1,467 @@
#ps1_sysnative
<#
Copyright 2014 Cloudbase Solutions Srl
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
#>
$utilsPath = (Resolve-Path '..\Common\heat-powershell-utils.psm1').Path
$modulePath = (Resolve-Path '..\IIS_Drupal.psm1').Path
Remove-Module IIS_Drupal -ErrorAction SilentlyContinue
Remove-Module heat-powershell-utils -ErrorAction SilentlyContinue
Import-Module -Name $modulePath -DisableNameChecking
Import-Module -Name $utilsPath -DisableNameChecking
InModuleScope IIS_Drupal {
Describe "Install-IIS" {
Context "IIS is installed" {
Mock LogTo-File { return 0 } -Verifiable
Mock Install-WindowsFeatures { return 0 } -Verifiable
$IISFeatures = @("Web-Server",
"Web-Http-Redirect",
"Web-DAV-Publishing",
"Web-Custom-Logging",
"Web-Log-Libraries",
"Web-ODBC-Logging",
"Web-Request-Monitor",
"Web-Http-Tracing",
"Web-Mgmt-Console",
"Web-Scripting-Tools",
"Web-Mgmt-Service",
"Web-CGI",
"NET-Framework-Core")
Install-IIS
It "should install all the features" {
Assert-MockCalled Install-WindowsFeatures -Exactly 1 `
-ParameterFilter { (((Compare-Object `
$Features $IISFeatures).InputObject).Length -eq 0) }
}
It "should log to file" {
Assert-MockCalled LogTo-File -Exactly 1
}
}
}
Describe "Install-SQLServerExpress2008R2SP2" {
Context "SQLEXPRESS is installed" {
Mock LogTo-File { return 0 } -Verifiable
Mock Install-Program { return 0 } -Verifiable
$fakeSAPassword = 'password'
$link = 'http://download.microsoft.com/download/0/4/B/' +
'04BE03CD-EAF3-4797-9D8D-2E08E316C998/SQLEXPR_x64_ENU.exe'
$hash = 'E768A3B70E3F3B596EFFA9F57D812F95C0A0506B'
$file = Join-Path $env:TEMP $link.Split('/')[-1]
$sqlArguments = @('/ACTION=Install',
'/Q',
'/IACCEPTSQLSERVERLICENSETERMS',
'/INSTANCENAME=SQLEXPRESS',
'/SECURITYMODE=SQL',
"/SAPWD=$fakeSAPassword",
'/SQLSYSADMINACCOUNTS="BUILTIN\Administrators"')
$sqlError = "Failed to install SQL Server 2008 R2 SP2 Express"
Install-SQLServerExpress2008R2SP2 $fakeSAPassword
It "should successfully install the program" {
Assert-MockCalled Install-Program -Exactly 1 -ParameterFilter `
{ ($DownloadLink -eq $link) -and
($ExpectedSHA1Hash -eq $hash) -and
($DestinationFile -eq $file) -and
($ErrorMessage -eq $sqlError) -and
(((Compare-Object `
$sqlArguments $Arguments).InputObject).Length -eq 0) }
}
It "should log to file" {
Assert-MockCalled LogTo-File -Exactly 1
}
}
}
Describe "Install-SevenZip" {
Context "7z 9.20 is installed" {
Mock LogTo-File { return 0 } -Verifiable
Mock Install-Program { return 0 } -Verifiable
$link = 'http://softlayer-ams.dl.sourceforge.net/project/' +
'sevenzip/7-Zip/9.20/7z920.msi'
$hash = 'C67D3F611EA3EB3336CF92F6FFCAFDB14F8B12AF'
$file = Join-Path $env:TEMP $link.Split('/')[-1]
$params = @("/Q")
$errMsg = "Failed to install 7-Zip 9.20"
Install-SevenZip
It "should successfully install 7z" {
Assert-MockCalled Install-Program -Exactly 1 -ParameterFilter `
{ ($DownloadLink -eq $link) -and
($ExpectedSHA1Hash -eq $hash) -and
($DestinationFile -eq $file) -and
($ErrorMessage -eq $errMsg) -and
(((Compare-Object `
$params $Arguments).InputObject).Length -eq 0) }
}
It "should log to file" {
Assert-MockCalled LogTo-File -Exactly 1
}
}
}
Describe "Install-SQLServerDriversForPHP" {
Context "PHP SQL Server drivers are installed" {
Mock LogTo-File { return 0 } -Verifiable
Mock Install-Program { return 0 } -Verifiable
Mock Copy-Item { return 0 } -Verifiable
Mock Remove-Item { return 0 } -Verifiable
$fakeExtLocation = "location"
$link = 'http://download.microsoft.com/download/C/D/B/' +
'CDB0A3BB-600E-42ED-8D5E-E4630C905371/SQLSRV30.EXE'
$hash = '1457A9F9B87119265966EEE6C9A648249A7A83E0'
$file = Join-Path $env:TEMP $link.Split('/')[-1]
$destination = Join-Path $env:TEMP "SQLDrivers"
$params = @("/Q",
"/T:$destination",
"/C")
$errMsg = "Failed to extract drivers into the specified path"
Install-SQLServerDriversForPHP $fakeExtLocation
It "should extract drivers" {
Assert-MockCalled Install-Program -Exactly 1 -ParameterFilter `
{ ($DownloadLink -eq $link) -and
($ExpectedSHA1Hash -eq $hash) -and
($DestinationFile -eq $file) -and
(((Compare-Object `
$params $Arguments).InputObject).Length -eq 0) -and
($errMsg -eq $ErrorMessage) }
}
It "should copy the files" {
Assert-MockCalled Copy-Item -Exactly 2
}
It "should remove temp file" {
Assert-MockCalled Remove-Item -Exactly 1
}
It "should log to file" {
Assert-MockCalled LogTo-File -Exactly 1
}
}
}
Describe "Add-PHPSettings" {
Context "PHP settings are added" {
Mock Set-IniFileValue { return 0 } -Verifiable
$fakeSettings = @{'key1' = 'value1';
'key2' = 'value2'}
$fakeIniPath = 'fakePath'
Add-PHPSettings $fakeSettings "DEFAULT" $fakeIniPath
It "should set php.ini values" {
Assert-MockCalled Set-IniFileValue -Exactly 2
}
}
}
Describe "Enable-PHPExtensions" {
Context "PHP extensions are enabled" {
Mock Set-IniFileValue { return 0 } -Verifiable
$fakeExtensions = @{'section1' = 'value1';
'section2' = 'value2'}
$fakeIniPath = 'fakePath'
Add-PHPSettings $fakeExtensions "DEFAULT" $fakeIniPath
It "should enable php.ini extensions" {
Assert-MockCalled Set-IniFileValue -Exactly 2
}
}
}
Describe "Configure-PHP54" {
Context "PHP54 is configured" {
Mock Copy-Item { return 0 } -Verifiable
Mock Set-IniFileValue { return 0 } -Verifiable
Mock Add-PHPSettings { return 0 } -Verifiable
Mock Enable-PHPExtensions { return 0 } -Verifiable
Mock Execute-Command { return 0 } -Verifiable
Mock LogTo-File { return 0 } -Verifiable
$fakePHPLocation = 'location1'
$fakeExtLocation = 'location2'
Configure-PHP54 -PHPLocation $fakePHPLocation `
-ExtLocation $fakeExtLocation
It "should create php.ini file" {
Assert-MockCalled Copy-Item -Exactly 1
}
It "should set php memory limit" {
Assert-MockCalled Set-IniFileValue -Exactly 1
}
It "should add desired php settings" {
Assert-MockCalled Add-PHPSettings -Exactly 1
}
It "should enable php extensions" {
Assert-MockCalled Enable-PHPExtensions -Exactly 1
}
It "should configure IIS for PHP" {
Assert-MockCalled Execute-Command -Exactly 4
}
It "should log to file" {
Assert-MockCalled LogTo-File -Exactly 1
}
}
}
Describe "Install-PHP54" {
Context "PHP54 is installed" {
Mock New-Item { return 0 } -Verifiable
Mock Download-File { return 0 } -Verifiable
Mock Check-FileIntegrityWithSHA1 { return 0 } -Verifiable
Mock Unzip-File { return 0 } -Verifiable
Mock Remove-Item { return 0 } -Verifiable
Mock Install-SQLServerDriversForPHP { return 0 } -Verifiable
Mock Configure-PHP54 { return 0 } -Verifiable
Mock LogTo-File { return 0 } -Verifiable
$fakePHPLocation = "location"
Install-PHP54 $fakePHPLocation
It "should create new folder for PHP" {
Assert-MockCalled New-Item -Exactly 1 `
-ParameterFilter { $ItemType -eq "Directory" }
}
It "should download PHP54" {
Assert-MockCalled Download-File -Exactly 1
}
It "should check file integrity" {
Assert-MockCalled Check-FileIntegrityWithSHA1 -Exactly 1
}
It "should unzip PHP 5.4" {
Assert-MockCalled Unzip-File -Exactly 1
}
It "should remove temporary file" {
Assert-MockCalled Remove-Item -Exactly 1
}
It "should install sql server drivers for PHP" {
Assert-MockCalled Install-SQLServerDriversForPHP -Exactly 1
}
It "should configure PHP 5.4" {
Assert-MockCalled Configure-PHP54 -Exactly 1
}
It "should log to file" {
Assert-MockCalled LogTo-File -Exactly 1
}
}
}
Describe "Install-Drupal7" {
Context "Drupal7 is installed" {
Mock Install-Program { return 0 } -Verifiable
Mock Download-File { return 0 } -Verifiable
Mock Check-FileIntegrityWithSHA1 { return 0 } -Verifiable
Mock Unzip-File { return 0 } -Verifiable
Mock New-Item { return 0 } -Verifiable
Mock Copy-Item { return 0 } -Verifiable
Mock Remove-Item { return 0 } -Verifiable
Mock Execute-Command { return 0 } -Verifiable
Mock Push-Location { return 0 } -Verifiable
Mock Pop-Location { return 0 } -Verifiable
Mock LogTo-File { return 0 } -Verifiable
$fakeSAPassword = "password"
$fakeAdminUsername = "admin"
$fakeAdminPassword = "password"
$fakeAdminEmail = "admin@admim.com"
$fakeWebsiteName = "website"
Install-Drupal7 $fakeSAPassword `
$fakeAdminUsername `
$fakeAdminPassword `
$fakeAdminEmail `
$fakeWebsiteName
It "should install every required program" {
Assert-MockCalled Install-Program -Exactly 4
}
It "should download every file" {
Assert-MockCalled Download-File -Exactly 2
}
It "should copy files" {
Assert-MockCalled Copy-Item -Exactly 3
}
It "should create new folders" {
Assert-MockCalled New-Item -Exactly 2 `
-ParameterFilter { $ItemType -eq "Directory" }
}
It "should check files for integrity" {
Assert-MockCalled Check-FileIntegrityWithSHA1 -Exactly 2
}
It "should unzip downloaded zip files" {
Assert-MockCalled Unzip-File -Exactly 2
}
It "should remove temporary files" {
Assert-MockCalled Remove-Item -Exactly 3
}
It "should execute configuration commands" {
Assert-MockCalled Execute-Command -Exactly 9
}
It "should Push-Location to Drupal web site location" {
Assert-MockCalled Push-Location -Exactly 1
}
It "should go to the previous location" {
Assert-MockCalled Pop-Location -Exactly 1
}
It "should log to file" {
Assert-MockCalled LogTo-File -Exactly 3
}
}
}
Describe "Install-IISWithDrupal" {
Context "Drupal7 on IIS is installed" {
Mock Install-IIS { return 0 } -Verifiable
Mock Install-SQLServerExpress2008R2SP2 { return 0 } -Verifiable
Mock Install-SevenZip { return 0 } -Verifiable
Mock Install-PHP54 { return 0 } -Verifiable
Mock Install-Drupal7 { return 0 } -Verifiable
$fakeParams = @{
'ENDPOINT' = 'token';
'TOKEN' = 'endpoint';
'SA_PASS' = 'password';
'ADMIN_USER' = 'user';
'ADMIN_PASS' = "password";
'ADMIN_EMAIL' = 'email';
'SITE_NAME' = "website"
}
$phpLoc = Join-Path $env:SystemDrive "PHP\PHP54"
Install-IISWithDrupal $fakeParams
It "should install IIS" {
Assert-MockCalled Install-IIS -Exactly 1
}
It "should install SQLServerExpress2008R2SP2" {
Assert-MockCalled Install-SQLServerExpress2008R2SP2 -Exactly 1 `
-ParameterFilter {
$SAPassword -eq $fakeParams['SA_PASS']
}
}
It "should install SevenZip" {
Assert-MockCalled Install-SevenZip -Exactly 1
}
It "should install PHP54" {
Assert-MockCalled Install-PHP54 -Exactly 1 `
-ParameterFilter {
$PHPLocation -eq $phpLoc
}
}
It "should install Drupal7" {
Assert-MockCalled Install-Drupal7 -Exactly 1 `
-ParameterFilter {
($SAPassword -eq $fakeParams['SA_PASS']) -and
($AdminUsername -eq $fakeParams['ADMIN_USER']) -and
($AdminPassword -eq $fakeParams['ADMIN_PASS']) -and
($AdminEmail -eq $fakeParams['ADMIN_EMAIL']) -and
($WebsiteName -eq $fakeParams['SITE_NAME'])
}
}
}
}
Describe "Initialize-Server" {
Mock LogTo-File { return 0 } -Verifiable
Mock Send-HeatWaitSignal { return 0 } -Verifiable
$fakeParams = @{
'ENDPOINT' = 'token';
'TOKEN' = 'endpoint';
'SA_PASS' = 'password';
'ADMIN_USER' = 'user';
'ADMIN_PASS' = "password";
'ADMIN_EMAIL' = 'email';
'SITE_NAME' = "website"
}
Context "Successful initialization" {
Mock Install-IISWithDrupal { return 0 } -Verifiable
Initialize-Server $fakeParams
It "should log to file" {
Assert-MockCalled LogTo-File -Exactly 2 -Scope Context
}
It "should install IIS with Drupal" {
Assert-MockCalled Install-IISWithDrupal -Exactly 1 `
-Scope Context
}
It "should send heat wait signal" {
Assert-MockCalled Send-HeatWaitSignal -Exactly 1 `
-Scope Context
}
}
Context "Unsuccessful initialization" {
Mock Install-IISWithDrupal { throw } -Verifiable
Initialize-Server $fakeParams
It "should log to file" {
Assert-MockCalled LogTo-File -Exactly 3 -Scope Context
}
It "should install IIS with Drupal" {
Assert-MockCalled Install-IISWithDrupal -Exactly 1 `
-Scope Context
}
It "should send heat wait signal" {
Assert-MockCalled Send-HeatWaitSignal -Exactly 1 `
-Scope Context
}
}
}
}