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:
parent
063e6a0930
commit
1068c8fe1a
390
hot/Windows/IIS_Drupal/Common/heat-powershell-utils.psm1
Normal file
390
hot/Windows/IIS_Drupal/Common/heat-powershell-utils.psm1
Normal 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 *
|
36
hot/Windows/IIS_Drupal/IIS_Drupal.ps1
Normal file
36
hot/Windows/IIS_Drupal/IIS_Drupal.ps1
Normal 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
|
416
hot/Windows/IIS_Drupal/IIS_Drupal.psm1
Normal file
416
hot/Windows/IIS_Drupal/IIS_Drupal.psm1
Normal 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
|
186
hot/Windows/IIS_Drupal/IIS_Drupal.yaml
Normal file
186
hot/Windows/IIS_Drupal/IIS_Drupal.yaml
Normal 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 ] }
|
467
hot/Windows/IIS_Drupal/Tests/IIS_Drupal.Tests.ps1
Normal file
467
hot/Windows/IIS_Drupal/Tests/IIS_Drupal.Tests.ps1
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user