From 7c6c03361907d95dd9cf603bb6fc3ca98f5f0d76 Mon Sep 17 00:00:00 2001 From: Aaron Zuehlke Date: Wed, 22 Apr 2015 09:57:02 -0500 Subject: [PATCH 1/9] Initial commit to merge the work done here https://github.com/PowerShellOrg/cWebAdministration on the App Pool resource --- .../MSFT_xWebAppPool/MSFT_xWebAppPool.psm1 | 1217 +++++++++++++++-- .../MSFT_xWebAppPool.schema.mof | 58 +- 2 files changed, 1177 insertions(+), 98 deletions(-) diff --git a/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.psm1 b/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.psm1 index f47f895c8..a76e87800 100644 --- a/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.psm1 +++ b/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.psm1 @@ -1,134 +1,1167 @@ -function Get-TargetResource +data LocalizedData { - [CmdletBinding()] - [OutputType([System.Collections.Hashtable])] - param - ( - [parameter(Mandatory = $true)] - [System.String] - $Name + # culture="en-US" + ConvertFrom-StringData @' +SetTargetResourceInstallwhatIfMessage=Trying to create AppPool "{0}". +SetTargetResourceUnInstallwhatIfMessage=Trying to remove AppPool "{0}". +AppPoolNotFoundError=The requested AppPool "{0}" is not found on the target machine. +AppPoolDiscoveryFailureError=Failure to get the requested AppPool "{0}" information from the target machine. +AppPoolCreationFailureError=Failure to successfully create the AppPool "{0}". +AppPoolRemovalFailureError=Failure to successfully remove the AppPool "{0}". +AppPoolUpdateFailureError=Failure to successfully update the properties for AppPool "{0}". +AppPoolCompareFailureError=Failure to successfully compare properties for AppPool "{0}". +AppPoolStateFailureError=Failure to successfully set the state of the AppPool {0}. +'@ +} + +# The Get-TargetResource cmdlet is used to fetch the status of role or AppPool on the target machine. +# It gives the AppPool info of the requested role/feature on the target machine. +function Get-TargetResource +{ + [OutputType([hashtable])] + param + ( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$Name ) - $Ensure = "Absent" - $State = "Stopped" + $getTargetResourceResult = $null; - #need to import explicitly to run for IIS:\AppPools - Import-Module WebAdministration + # Check if WebAdministration module is present for IIS cmdlets + if(!(Get-Module -ListAvailable -Name WebAdministration)) + { + Throw "Please ensure that WebAdministration module is installed." + } - if(!(Get-Module -ListAvailable -Name WebAdministration)) - { - Throw "Please ensure that WebAdministration module is installed." - } + $AppPools = & $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $Name - $AppPool = Get-Item -Path IIS:\AppPools\* | ? {$_.name -eq $Name} + if ($AppPools.count -eq 0) # No AppPool exists with this name. + { + $ensureResult = "Absent"; + } + elseif ($AppPools.count -eq 1) # A single AppPool exists with this name. + { + $ensureResult = "Present" + $AppPoolState = & $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $Name /text:state + [xml] $PoolConfig + $PoolConfig = & $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $Name /config:* + if($PoolConfig.add.processModel.userName){ + $AppPoolPassword = $PoolConfig.add.processModel.password | ConvertTo-SecureString -AsPlainText -Force + $AppPoolCred = new-object -typename System.Management.Automation.PSCredential -argumentlist $PoolConfig.add.processModel.userName,$AppPoolPassword + } + else{ + $AppPoolCred =$null + } - if($AppPool -ne $null) - { - $Ensure = "Present" - $State = $AppPool.state - } + } + else # Multiple AppPools with the same name exist. This is not supported and is an error + { + $errorId = "AppPoolDiscoveryFailure"; + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult + $errorMessage = $($LocalizedData.AppPoolUpdateFailureError) -f ${Name} + $exception = New-Object System.InvalidOperationException $errorMessage + $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null - $returnValue = @{ - Name = $Name - Ensure = $Ensure - State = $State - } + $PSCmdlet.ThrowTerminatingError($errorRecord); + } - return $returnValue + # Add all Website properties to the hash table + $getTargetResourceResult = @{ + Name = $PoolConfig.add.name; + Ensure = $ensureResult; + State = $AppPoolState; + autoStart = $PoolConfig.add.autoStart; + managedRuntimeVersion = $PoolConfig.add.managedRuntimeVersion; + managedPipelineMode = $PoolConfig.add.managedPipelineMode; + startMode = $PoolConfig.add.startMode; + identityType = $PoolConfig.add.processModel.identityType; + userName = $PoolConfig.add.processModel.userName; + password = $AppPoolCred; + loadUserProfile = $PoolConfig.add.processModel.loadUserProfile; + queueLength = $PoolConfig.add.queueLength; + enable32BitAppOnWin64 = $PoolConfig.add.enable32BitAppOnWin64; + managedRuntimeLoader = $PoolConfig.add.managedRuntimeLoader; + enableConfigurationOverride = $PoolConfig.add.enableConfigurationOverride; + CLRConfigFile = $PoolConfig.add.CLRConfigFile; + passAnonymousToken = $PoolConfig.add.passAnonymousToken; + logonType = $PoolConfig.add.processModel.logonType; + manualGroupMembership = $PoolConfig.add.processModel.manualGroupMembership; + idleTimeout = $PoolConfig.add.processModel.idleTimeout; + maxProcesses = $PoolConfig.add.processModel.maxProcesses; + shutdownTimeLimit = $PoolConfig.add.processModel.shutdownTimeLimit; + startupTimeLimit = $PoolConfig.add.processModel.startupTimeLimit; + pingingEnabled = $PoolConfig.add.processModel.pingingEnabled; + pingInterval = $PoolConfig.add.processModel.pingInterval; + pingResponseTime = $PoolConfig.add.processModel.pingResponseTime; + disallowOverlappingRotation = $PoolConfig.add.recycling.disallowOverlappingRotation; + disallowRotationOnConfigChange = $PoolConfig.add.recycling.disallowRotationOnConfigChange; + logEventOnRecycle = $PoolConfig.add.recycling.logEventOnRecycle; + restartMemoryLimit = $PoolConfig.add.recycling.periodicRestart.memory; + restartPrivateMemoryLimit = $PoolConfig.add.recycling.periodicRestart.privateMemory; + restartRequestsLimit = $PoolConfig.add.recycling.periodicRestart.requests; + restartTimeLimit = $PoolConfig.add.recycling.periodicRestart.time; + restartSchedule = $PoolConfig.add.recycling.periodicRestart.schedule; + loadBalancerCapabilities = $PoolConfig.add.failure.loadBalancerCapabilities; + orphanWorkerProcess = $PoolConfig.add.failure.orphanWorkerProcess; + orphanActionExe = $PoolConfig.add.failure.orphanActionExe; + orphanActionParams = $PoolConfig.add.failure.orphanActionParams; + rapidFailProtection = $PoolConfig.add.failure.rapidFailProtection; + rapidFailProtectionInterval = $PoolConfig.add.failure.rapidFailProtectionInterval; + rapidFailProtectionMaxCrashes = $PoolConfig.add.failure.rapidFailProtectionMaxCrashes; + autoShutdownExe = $PoolConfig.add.failure.autoShutdownExe; + autoShutdownParams = $PoolConfig.add.failure.autoShutdownParams; + cpuLimit = $PoolConfig.add.cpu.limit; + cpuAction = $PoolConfig.add.cpu.action; + cpuResetInterval = $PoolConfig.add.cpu.resetInterval; + cpuSmpAffinitized = $PoolConfig.add.cpu.smpAffinitized; + cpuSmpProcessorAffinityMask = $PoolConfig.add.cpu.smpProcessorAffinityMask; + cpuSmpProcessorAffinityMask2 = $PoolConfig.add.cpu.smpProcessorAffinityMask2; + } + + return $getTargetResourceResult; } -function Set-TargetResource +# The Set-TargetResource cmdlet is used to create, delete or configure a website on the target machine. +function Set-TargetResource { - [CmdletBinding()] - param - ( - [parameter(Mandatory = $true)] - [System.String] - $Name, + [CmdletBinding(SupportsShouldProcess=$true)] + param + ( + [ValidateSet("Present", "Absent")] + [string]$Ensure = "Present", - [ValidateSet("Present","Absent")] - [System.String] - $Ensure = "Present", + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$Name, [ValidateSet("Started","Stopped")] - [System.String] - $State = "Started" + [string]$state = "Started", + + [ValidateSet("true","false")] + [string]$autoStart = "true", + + [ValidateSet("v4.0","v2.0","")] + [string]$managedRuntimeVersion = "v4.0", + + [ValidateSet("Integrated","Classic")] + [string]$managedPipelineMode = "Integrated", + + [ValidateSet("AlwaysRunning","OnDemand")] + [string]$startMode = "OnDemand", + + [ValidateSet("ApplicationPoolIdentity","LocalSystem","LocalService","NetworkService","SpecificUser")] + [string]$identityType = "ApplicationPoolIdentity", + + [string]$userName, + + [System.Management.Automation.PSCredential] + $Password, + + [ValidateSet("true","false")] + [string]$loadUserProfile = "true", + + [string]$queueLength = "1000", + + [ValidateSet("true","false")] + [string]$enable32BitAppOnWin64 = "false", + + [string]$managedRuntimeLoader = "webengine4.dll", + + [ValidateSet("true","false")] + [string]$enableConfigurationOverride = "true", + + [string]$CLRConfigFile = "", + + [ValidateSet("true","false")] + [string]$passAnonymousToken = "true", + + [ValidateSet("LogonBatch","LogonService")] + [string]$logonType = "LogonBatch", + + [ValidateSet("true","false")] + [string]$manualGroupMembership = "false", + + #Format 00:20:00 + [string]$idleTimeout = "00:20:00", + + [string]$maxProcesses = "1", + + #Format 00:20:00 + [string]$shutdownTimeLimit = "00:01:30", + + #Format 00:20:00 + [string]$startupTimeLimit = "00:01:30", + + [ValidateSet("true","false")] + [string]$pingingEnabled = "true", + + #Format 00:20:00 + [string]$pingInterval = "00:00:30", + + #Format 00:20:00 + [string]$pingResponseTime = "00:01:30", + + [ValidateSet("true","false")] + [string]$disallowOverlappingRotation = "false", + + [ValidateSet("true","false")] + [string]$disallowRotationOnConfigChange = "false", + + #format "Time, Memory, PrivateMemory" + [string]$logEventOnRecycle = "Time, Memory, PrivateMemory", + + [string]$restartMemoryLimit = "0", + + [string]$restartPrivateMemoryLimit = "0", + + [string]$restartRequestsLimit = "0", + + [string]$restartTimeLimit = "1.05:00:00", + + #Format 00:00:00 24hr clock and must have 00 for seconds + [string[]]$restartSchedule = @(""), + + [ValidateSet("HttpLevel","TcpLevel")] + [string]$loadBalancerCapabilities = "HttpLevel", + + [ValidateSet("true","false")] + [string]$orphanWorkerProcess = "false", + + [string]$orphanActionExe = "", + + [string]$orphanActionParams = "", + + [ValidateSet("true","false")] + [string]$rapidFailProtection = "true", + + #Format 00:20:00 + [string]$rapidFailProtectionInterval = "00:05:00", + + [string]$rapidFailProtectionMaxCrashes = "5", + + [string]$autoShutdownExe = "", + + [string]$autoShutdownParams = "", + + [string]$cpuLimit = "0", + + [ValidateSet("NoAction","KillW3wp","Throttle","ThrottleUnderLoad")] + [string]$cpuAction = "NoAction", + + #Format 00:20:00 + [string]$cpuResetInterval = "00:05:00", + + [ValidateSet("true","false")] + [string]$cpuSmpAffinitized = "false", + + [string]$cpuSmpProcessorAffinityMask = "4294967295", + + [string]$cpuSmpProcessorAffinityMask2 = "4294967295" ) + + $getTargetResourceResult = $null; - if($Ensure -eq "Absent") - { - Write-Verbose("Removing the Web App Pool") - Remove-WebAppPool $Name - } - else + if($Ensure -eq "Present") { - $AppPool = Get-TargetResource -Name $Name - if($AppPool.Ensure -ne "Present") + #Remove Ensure from parameters as it is not needed to create new AppPool + $Result = $psboundparameters.Remove("Ensure"); + + + # Check if WebAdministration module is present for IIS cmdlets + if(!(Get-Module -ListAvailable -Name WebAdministration)) { - Write-Verbose("Creating the Web App Pool") - New-WebAppPool $Name - $AppPool = Get-TargetResource -Name $Name + Throw "Please ensure that WebAdministration module is installed." } - if($AppPool.State -ne $State) + $AppPool = & $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $Name + + if($AppPool -eq $null) #AppPool doesn't exist so create a new one + { + try + { + New-WebAppPool $Name + Wait-Event -Timeout 5 + Stop-WebAppPool $Name + + Write-Verbose("successfully created AppPool $Name") + + #Start site if required + if($autoStart -eq "true") + { + Start-WebAppPool $Name + } + + Write-Verbose("successfully started AppPool $Name") + + $AppPool = & $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $Name + } + catch + { + $errorId = "AppPoolCreationFailure"; + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation; + $errorMessage = $($LocalizedData.FeatureCreationFailureError) -f ${Name} ; + $exception = New-Object System.InvalidOperationException $errorMessage ; + $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null + + $PSCmdlet.ThrowTerminatingError($errorRecord); + } + } + + if($AppPool -ne $null) + { + #update parameters as required + + $UpdateNotRequired = $true + + #get configuration of AppPool + #[xml] $PoolConfig + [xml]$PoolConfig = & $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $Name /config:* + + #Update autoStart if required + if($PoolConfig.add.autoStart -ne $autoStart){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /autoStart:$autoStart + } + + #update managedRuntimeVersion if required + if($PoolConfig.add.managedRuntimeVersion -ne $managedRuntimeVersion){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /managedRuntimeVersion:$managedRuntimeVersion + } + #update managedPipelineMode if required + if($PoolConfig.add.managedPipelineMode -ne $managedPipelineMode){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /managedPipelineMode:$managedPipelineMode + } + #update state if required + if($AppPoolState -ne $state){ + $UpdateNotRequired = $false + if($State -eq "Started") + { + start-WebAppPool -Name $Name + } + else + { + Stop-WebAppPool -Name $Name + } + } + #update startMode if required + if($PoolConfig.add.startMode -ne $startMode){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /startMode:$startMode + } + #update identityType if required + if($PoolConfig.add.processModel.identityType -ne $identityType){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /processModel.identityType:$identityType + } + #update userName if required + if($identityType -eq "SpecificUser" -and $PoolConfig.add.processModel.userName -ne $userName){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /processModel.userName:$userName + } + #update password if required + if($identityType -eq "SpecificUser" -and $Password){ + $clearTextPassword = $Password.GetNetworkCredential().Password + if($clearTextPassword -cne $PoolConfig.add.processModel.password){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /processModel.password:$clearTextPassword + } + + } + + #update loadUserProfile if required + if($PoolConfig.add.processModel.loadUserProfile -ne $loadUserProfile){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /processModel.loadUserProfile:$loadUserProfile + } + + #update queueLength if required + if($PoolConfig.add.queueLength -ne $queueLength){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /queueLength:$queueLength + } + + #update enable32BitAppOnWin64 if required + if($PoolConfig.add.enable32BitAppOnWin64 -ne $enable32BitAppOnWin64){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /enable32BitAppOnWin64:$enable32BitAppOnWin64 + } + + #update managedRuntimeLoader if required + if($PoolConfig.add.managedRuntimeLoader -ne $managedRuntimeLoader){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /managedRuntimeLoader:$managedRuntimeLoader + } + + #update enableConfigurationOverride if required + if($PoolConfig.add.enableConfigurationOverride -ne $enableConfigurationOverride){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /enableConfigurationOverride:$enableConfigurationOverride + } + + #update CLRConfigFile if required + if($PoolConfig.add.CLRConfigFile -ne $CLRConfigFile){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /CLRConfigFile:$CLRConfigFile + } + + #update passAnonymousToken if required + if($PoolConfig.add.passAnonymousToken -ne $passAnonymousToken){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /passAnonymousToken:$passAnonymousToken + } + + #update logonType if required + if($PoolConfig.add.processModel.logonType -ne $logonType){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /processModel.logonType:$logonType + } + + #update manualGroupMembership if required + if($PoolConfig.add.processModel.manualGroupMembership -ne $manualGroupMembership){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /processModel.manualGroupMembership:$manualGroupMembership + } + + #update idleTimeout if required + if($PoolConfig.add.processModel.idleTimeout -ne $idleTimeout){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /processModel.idleTimeout:$idleTimeout + } + + #update maxProcesses if required + if($PoolConfig.add.processModel.maxProcesses -ne $maxProcesses){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /processModel.maxProcesses:$maxProcesses + } + + #update shutdownTimeLimit if required + if($PoolConfig.add.processModel.shutdownTimeLimit -ne $shutdownTimeLimit){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /processModel.shutdownTimeLimit:$shutdownTimeLimit + } + + #update startupTimeLimit if required + if($PoolConfig.add.processModel.startupTimeLimit -ne $startupTimeLimit){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /processModel.startupTimeLimit:$startupTimeLimit + } + + #update pingingEnabled if required + if($PoolConfig.add.processModel.pingingEnabled -ne $pingingEnabled){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /processModel.pingingEnabled:$pingingEnabled + } + + #update pingInterval if required + if($PoolConfig.add.processModel.pingInterval -ne $pingInterval){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /processModel.pingInterval:$pingInterval + } + + #update pingResponseTime if required + if($PoolConfig.add.processModel.pingResponseTime -ne $pingResponseTime){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /processModel.pingResponseTime:$pingResponseTime + } + + #update disallowOverlappingRotation if required + if($PoolConfig.add.recycling.disallowOverlappingRotation -ne $disallowOverlappingRotation){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /recycling.disallowOverlappingRotation:$disallowOverlappingRotation + } + + #update disallowRotationOnConfigChange if required + if($PoolConfig.add.recycling.disallowRotationOnConfigChange -ne $disallowRotationOnConfigChange){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /recycling.disallowRotationOnConfigChange:$disallowRotationOnConfigChange + } + + #update logEventOnRecycle if required + if($PoolConfig.add.recycling.logEventOnRecycle -ne $logEventOnRecycle){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /recycling.logEventOnRecycle:$logEventOnRecycle + } + + #update restartMemoryLimit if required + if($PoolConfig.add.recycling.periodicRestart.memory -ne $restartMemoryLimit){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /recycling.periodicRestart.memory:$restartMemoryLimit + } + + #update restartPrivateMemoryLimit if required + if($PoolConfig.add.recycling.periodicRestart.privateMemory -ne $restartPrivateMemoryLimit){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /recycling.periodicRestart.privateMemory:$restartPrivateMemoryLimit + } + + #update restartRequestsLimit if required + if($PoolConfig.add.recycling.periodicRestart.requests -ne $restartRequestsLimit){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /recycling.periodicRestart.requests:$restartRequestsLimit + } + + #update restartTimeLimit if required + if($PoolConfig.add.recycling.periodicRestart.time -ne $restartTimeLimit){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /recycling.periodicRestart.time:$restartTimeLimit + } + + #update restartSchedule if required + #clear current schedule + foreach($schTime in $PoolConfig.add.recycling.periodicRestart.schedule.add.value) + { + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name "/-recycling.periodicRestart.schedule.[value='$schTime']" + } + #add desired schedule + foreach($time in $restartSchedule) + { + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name "/+recycling.periodicRestart.schedule.[value='$time']" + } + + #update loadBalancerCapabilities if required + if($PoolConfig.add.failure.loadBalancerCapabilities -ne $loadBalancerCapabilities){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /failure.loadBalancerCapabilities:$loadBalancerCapabilities + } + + #update orphanWorkerProcess if required + if($PoolConfig.add.failure.orphanWorkerProcess -ne $orphanWorkerProcess){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /failure.orphanWorkerProcess:$orphanWorkerProcess + } + + #update orphanActionExe if required + if($PoolConfig.add.failure.orphanActionExe -ne $orphanActionExe){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /failure.orphanActionExe:$orphanActionExe + } + + #update orphanActionParams if required + if($PoolConfig.add.failure.orphanActionParams -ne $orphanActionParams){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /failure.orphanActionParams:$orphanActionParams + } + + #update rapidFailProtection if required + if($PoolConfig.add.failure.rapidFailProtection -ne $rapidFailProtection){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /failure.rapidFailProtection:$rapidFailProtection + } + + #update rapidFailProtectionInterval if required + if($PoolConfig.add.failure.rapidFailProtectionInterval -ne $rapidFailProtectionInterval){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /failure.rapidFailProtectionInterval:$rapidFailProtectionInterval + } + + #update rapidFailProtectionMaxCrashes if required + if($PoolConfig.add.failure.rapidFailProtectionMaxCrashes -ne $rapidFailProtectionMaxCrashes){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /failure.rapidFailProtectionMaxCrashes:$rapidFailProtectionMaxCrashes + } + + #update autoShutdownExe if required + if($PoolConfig.add.failure.autoShutdownExe -ne $autoShutdownExe){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /failure.autoShutdownExe:$autoShutdownExe + } + + #update autoShutdownParams if required + if($PoolConfig.add.failure.autoShutdownParams -ne $autoShutdownParams){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /failure.autoShutdownParams:$autoShutdownParams + } + + #update cpuLimit if required + if($PoolConfig.add.cpu.limit -ne $cpuLimit){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /cpu.limit:$cpuLimit + } + + #update cpuAction if required + if($PoolConfig.add.cpu.action -ne $cpuAction){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /cpu.action:$cpuAction + } + + #update cpuResetInterval if required + if($PoolConfig.add.cpu.resetInterval -ne $cpuResetInterval){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /cpu.resetInterval:$cpuResetInterval + } + + #update cpuSmpAffinitized if required + if($PoolConfig.add.cpu.smpAffinitized -ne $cpuSmpAffinitized){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /cpu.smpAffinitized:$cpuSmpAffinitized + } + + #update cpuSmpProcessorAffinityMask if required + if($PoolConfig.add.cpu.smpProcessorAffinityMask -ne $cpuSmpProcessorAffinityMask){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /cpu.smpProcessorAffinityMask:$cpuSmpProcessorAffinityMask + } + + #update cpuSmpProcessorAffinityMask2 if required + if($PoolConfig.add.cpu.smpProcessorAffinityMask2 -ne $cpuSmpProcessorAffinityMask2){ + $UpdateNotRequired = $false + & $env:SystemRoot\system32\inetsrv\appcmd.exe set apppool $Name /cpu.smpProcessorAffinityMask2:$cpuSmpProcessorAffinityMask2 + } + + if($UpdateNotRequired) + { + Write-Verbose("AppPool $Name already exists and properties do not need to be updated."); + } + + } + + } + else #Ensure is set to "Absent" so remove website + { + try + { + $AppPool = & $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $Name + if($AppPool -ne $null) + { + Stop-WebAppPool $Name + Remove-WebAppPool $Name + + Write-Verbose("Successfully removed AppPool $Name.") + } + else + { + Write-Verbose("AppPool $Name does not exist.") + } + } + catch { - ExecuteRequiredState -Name $Name -State $State + $errorId = "AppPoolRemovalFailure"; + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation; + $errorMessage = $($LocalizedData.WebsiteRemovalFailureError) -f ${Name} ; + $exception = New-Object System.InvalidOperationException $errorMessage ; + $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null + + $PSCmdlet.ThrowTerminatingError($errorRecord); } + } } -function Test-TargetResource +# The Test-TargetResource cmdlet is used to validate if the role or feature is in a state as expected in the instance document. +function Test-TargetResource { - [CmdletBinding()] - [OutputType([System.Boolean])] - param - ( - [parameter(Mandatory = $true)] - [System.String] - $Name, - - [ValidateSet("Present","Absent")] - [System.String] - $Ensure = "Present", + [OutputType([bool])] + param + ( + [ValidateSet("Present", "Absent")] + [string]$Ensure = "Present", + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$Name, [ValidateSet("Started","Stopped")] - [System.String] - $State = "Started" + [string]$state = "Started", + + [ValidateSet("true","false")] + [string]$autoStart = "true", + + [ValidateSet("v4.0","v2.0","")] + [string]$managedRuntimeVersion = "v4.0", + + [ValidateSet("Integrated","Classic")] + [string]$managedPipelineMode = "Integrated", + + [ValidateSet("AlwaysRunning","OnDemand")] + [string]$startMode = "OnDemand", + + [ValidateSet("ApplicationPoolIdentity","LocalSystem","LocalService","NetworkService","SpecificUser")] + [string]$identityType = "ApplicationPoolIdentity", + + [string]$userName, + + [System.Management.Automation.PSCredential] + $Password, + + [ValidateSet("true","false")] + [string]$loadUserProfile = "true", + + [string]$queueLength = "1000", + + [ValidateSet("true","false")] + [string]$enable32BitAppOnWin64 = "false", + + [string]$managedRuntimeLoader = "webengine4.dll", + + [ValidateSet("true","false")] + [string]$enableConfigurationOverride = "true", + + [string]$CLRConfigFile = "", + + [ValidateSet("true","false")] + [string]$passAnonymousToken = "true", + + [ValidateSet("LogonBatch","LogonService")] + [string]$logonType = "LogonBatch", + + [ValidateSet("true","false")] + [string]$manualGroupMembership = "false", + + #Format 00:20:00 + [string]$idleTimeout = "00:20:00", + + [string]$maxProcesses = "1", + + #Format 00:20:00 + [string]$shutdownTimeLimit = "00:01:30", + + #Format 00:20:00 + [string]$startupTimeLimit = "00:01:30", + + [ValidateSet("true","false")] + [string]$pingingEnabled = "true", + + #Format 00:20:00 + [string]$pingInterval = "00:00:30", + + #Format 00:20:00 + [string]$pingResponseTime = "00:01:30", + + [ValidateSet("true","false")] + [string]$disallowOverlappingRotation = "false", + + [ValidateSet("true","false")] + [string]$disallowRotationOnConfigChange = "false", + + #format "Time, Memory, PrivateMemory" + [string]$logEventOnRecycle = "Time, Memory, PrivateMemory", + + [string]$restartMemoryLimit = "0", + + [string]$restartPrivateMemoryLimit = "0", + + [string]$restartRequestsLimit = "0", + + [string]$restartTimeLimit = "1.05:00:00", + + #Format 00:00:00 24hr clock and must have 00 for seconds + [string[]]$restartSchedule = @(""), + + [ValidateSet("HttpLevel","TcpLevel")] + [string]$loadBalancerCapabilities = "HttpLevel", + + [ValidateSet("true","false")] + [string]$orphanWorkerProcess = "false", + + [string]$orphanActionExe = "", + + [string]$orphanActionParams = "", + + [ValidateSet("true","false")] + [string]$rapidFailProtection = "true", + + #Format 00:20:00 + [string]$rapidFailProtectionInterval = "00:05:00", + + [string]$rapidFailProtectionMaxCrashes = "5", + + [string]$autoShutdownExe = "", + + [string]$autoShutdownParams = "", + + [string]$cpuLimit = "0", + + [ValidateSet("NoAction","KillW3wp","Throttle","ThrottleUnderLoad")] + [string]$cpuAction = "NoAction", + + #Format 00:20:00 + [string]$cpuResetInterval = "00:05:00", + + [ValidateSet("true","false")] + [string]$cpuSmpAffinitized = "false", + + [string]$cpuSmpProcessorAffinityMask = "4294967295", + + [string]$cpuSmpProcessorAffinityMask2 = "4294967295" ) - $WebAppPool = Get-TargetResource -Name $Name + + $DesiredConfigurationMatch = $true - if($Ensure -eq "Present") + # Check if WebAdministration module is present for IIS cmdlets + if(!(Get-Module -ListAvailable -Name WebAdministration)) { - if($WebAppPool.Ensure -eq $Ensure -and $WebAppPool.State -eq $state) - { - return $true - } + Throw "Please ensure that WebAdministration module is installed." } - elseif($WebAppPool.Ensure -eq $Ensure) - { - return $true + + $AppPool = & $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $Name + if($AppPool){ + #get configuration of AppPool + #[xml] $PoolConfig + [xml]$PoolConfig = & $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $Name /config:* + $AppPoolState = & $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $Name /text:state } + $Stop = $true - return $false -} + Do + { + #Check Ensure + if(($Ensure -eq "Present" -and $AppPool -eq $null) -or ($Ensure -eq "Absent" -and $AppPool -ne $null)) + { + $DesiredConfigurationMatch = $false + Write-Verbose("The Ensure state for AppPool $Name does not match the desired state."); + break + } + # Only check properties if $AppPool exists + if ($AppPool -ne $null) + { + #Check autoStart + if($PoolConfig.add.autoStart -ne $autoStart){ + $DesiredConfigurationMatch = $false + Write-Verbose("autoStart of AppPool $Name does not match the desired state."); + break + } -function ExecuteRequiredState([string] $Name, [string] $State) -{ - if($State -eq "Started") - { - Write-Verbose("Starting the Web App Pool") - start-WebAppPool -Name $Name - } - else - { - Write-Verbose("Stopping the Web App Pool") - Stop-WebAppPool -Name $Name - } -} + #Check managedRuntimeVersion + if($PoolConfig.add.managedRuntimeVersion -ne $managedRuntimeVersion){ + $DesiredConfigurationMatch = $false + Write-Verbose("managedRuntimeVersion of AppPool $Name does not match the desired state."); + break + } + + #Check managedPipelineMode + if($PoolConfig.add.managedPipelineMode -ne $managedPipelineMode){ + $DesiredConfigurationMatch = $false + Write-Verbose("managedPipelineMode of AppPool $Name does not match the desired state."); + break + } + + #Check state + if($AppPoolState -ne $state){ + $DesiredConfigurationMatch = $false + Write-Verbose("state of AppPool $Name does not match the desired state."); + break + } + + #Check startMode + if($PoolConfig.add.startMode -ne $startMode){ + $DesiredConfigurationMatch = $false + Write-Verbose("startMode of AppPool $Name does not match the desired state."); + break + } + + #Check identityType + if($PoolConfig.add.processModel.identityType -ne $identityType){ + $DesiredConfigurationMatch = $false + Write-Verbose("identityType of AppPool $Name does not match the desired state."); + break + } + + #Check userName + if($PoolConfig.add.processModel.userName -ne $userName){ + $DesiredConfigurationMatch = $false + Write-Verbose("userName of AppPool $Name does not match the desired state."); + break + } + + #Check password + if($identityType -eq "SpecificUser" -and $Password){ + $clearTextPassword = $Password.GetNetworkCredential().Password + if($clearTextPassword -cne $PoolConfig.add.processModel.password){ + $DesiredConfigurationMatch = $false + Write-Verbose("Password of AppPool $Name does not match the desired state."); + break + } + } + + #Check loadUserProfile + if($PoolConfig.add.processModel.loadUserProfile -ne $loadUserProfile){ + $DesiredConfigurationMatch = $false + Write-Verbose("loadUserProfile of AppPool $Name does not match the desired state."); + break + } + + #Check queueLength + if($PoolConfig.add.queueLength -ne $queueLength){ + $DesiredConfigurationMatch = $false + Write-Verbose("queueLength of AppPool $Name does not match the desired state."); + break + } + + #Check enable32BitAppOnWin64 + if($PoolConfig.add.enable32BitAppOnWin64 -ne $enable32BitAppOnWin64){ + $DesiredConfigurationMatch = $false + Write-Verbose("enable32BitAppOnWin64 of AppPool $Name does not match the desired state."); + break + } + + #Check managedRuntimeLoader + if($PoolConfig.add.managedRuntimeLoader -ne $managedRuntimeLoader){ + $DesiredConfigurationMatch = $false + Write-Verbose("managedRuntimeLoader of AppPool $Name does not match the desired state."); + break + } + + #Check enableConfigurationOverride + if($PoolConfig.add.enableConfigurationOverride -ne $enableConfigurationOverride){ + $DesiredConfigurationMatch = $false + Write-Verbose("enableConfigurationOverride of AppPool $Name does not match the desired state."); + break + } + + #Check CLRConfigFile + if($PoolConfig.add.CLRConfigFile -ne $CLRConfigFile){ + $DesiredConfigurationMatch = $false + Write-Verbose("CLRConfigFile of AppPool $Name does not match the desired state."); + break + } + + #Check passAnonymousToken + if($PoolConfig.add.passAnonymousToken -ne $passAnonymousToken){ + $DesiredConfigurationMatch = $false + Write-Verbose("passAnonymousToken of AppPool $Name does not match the desired state."); + break + } + + #Check logonType + if($PoolConfig.add.processModel.logonType -ne $logonType){ + $DesiredConfigurationMatch = $false + Write-Verbose("logonType of AppPool $Name does not match the desired state."); + break + } + + #Check manualGroupMembership + if($PoolConfig.add.processModel.manualGroupMembership -ne $manualGroupMembership){ + $DesiredConfigurationMatch = $false + Write-Verbose("manualGroupMembership of AppPool $Name does not match the desired state."); + break + } + + #Check idleTimeout + if($PoolConfig.add.processModel.idleTimeout -ne $idleTimeout){ + $DesiredConfigurationMatch = $false + Write-Verbose("idleTimeout of AppPool $Name does not match the desired state."); + break + } + + #Check maxProcesses + if($PoolConfig.add.processModel.maxProcesses -ne $maxProcesses){ + $DesiredConfigurationMatch = $false + Write-Verbose("maxProcesses of AppPool $Name does not match the desired state."); + break + } + + #Check shutdownTimeLimit + if($PoolConfig.add.processModel.shutdownTimeLimit -ne $shutdownTimeLimit){ + $DesiredConfigurationMatch = $false + Write-Verbose("shutdownTimeLimit of AppPool $Name does not match the desired state."); + break + } + + #Check startupTimeLimit + if($PoolConfig.add.processModel.startupTimeLimit -ne $startupTimeLimit){ + $DesiredConfigurationMatch = $false + Write-Verbose("startupTimeLimit of AppPool $Name does not match the desired state."); + break + } + + #Check pingingEnabled + if($PoolConfig.add.processModel.pingingEnabled -ne $pingingEnabled){ + $DesiredConfigurationMatch = $false + Write-Verbose("pingingEnabled of AppPool $Name does not match the desired state."); + break + } + + #Check pingInterval + if($PoolConfig.add.processModel.pingInterval -ne $pingInterval){ + $DesiredConfigurationMatch = $false + Write-Verbose("pingInterval of AppPool $Name does not match the desired state."); + break + } -Export-ModuleMember -Function *-TargetResource + #Check pingResponseTime + if($PoolConfig.add.processModel.pingResponseTime -ne $pingResponseTime){ + $DesiredConfigurationMatch = $false + Write-Verbose("pingResponseTime of AppPool $Name does not match the desired state."); + break + } + #Check disallowOverlappingRotation + if($PoolConfig.add.recycling.disallowOverlappingRotation -ne $disallowOverlappingRotation){ + $DesiredConfigurationMatch = $false + Write-Verbose("disallowOverlappingRotation of AppPool $Name does not match the desired state."); + break + } + #Check disallowRotationOnConfigChange + if($PoolConfig.add.recycling.disallowRotationOnConfigChange -ne $disallowRotationOnConfigChange){ + $DesiredConfigurationMatch = $false + Write-Verbose("disallowRotationOnConfigChange of AppPool $Name does not match the desired state."); + break + } + + #Check logEventOnRecycle + if($PoolConfig.add.recycling.logEventOnRecycle -ne $logEventOnRecycle){ + $DesiredConfigurationMatch = $false + Write-Verbose("logEventOnRecycle of AppPool $Name does not match the desired state."); + break + } + + #Check restartMemoryLimit + if($PoolConfig.add.recycling.periodicRestart.memory -ne $restartMemoryLimit){ + $DesiredConfigurationMatch = $false + Write-Verbose("restartMemoryLimit of AppPool $Name does not match the desired state."); + break + } + + #Check restartPrivateMemoryLimit + if($PoolConfig.add.recycling.periodicRestart.privateMemory -ne $restartPrivateMemoryLimit){ + $DesiredConfigurationMatch = $false + Write-Verbose("restartPrivateMemoryLimit of AppPool $Name does not match the desired state."); + break + } + + #Check restartRequestsLimit + if($PoolConfig.add.recycling.periodicRestart.requests -ne $restartRequestsLimit){ + $DesiredConfigurationMatch = $false + Write-Verbose("restartRequestsLimit of AppPool $Name does not match the desired state."); + break + } + + #Check restartTimeLimit + if($PoolConfig.add.recycling.periodicRestart.time -ne $restartTimeLimit){ + $DesiredConfigurationMatch = $false + Write-Verbose("restartTimeLimit of AppPool $Name does not match the desired state."); + break + } + + #Check restartSchedule + if(($PoolConfig.add.recycling.periodicRestart.schedule.add.value -ne $null) -and ((Compare-Object $restartSchedule $PoolConfig.add.recycling.periodicRestart.schedule.add.value) -ne $null)){ + $DesiredConfigurationMatch = $false + Write-Verbose("restartTimeLimit of AppPool $Name does not match the desired state."); + break + } + if(($PoolConfig.add.recycling.periodicRestart.schedule.add.value -eq $null) -and ($restartSchedule -ne $null)){ + $DesiredConfigurationMatch = $false + Write-Verbose("restartTimeLimit of AppPool $Name does not match the desired state."); + break + } + + #Check loadBalancerCapabilities + if($PoolConfig.add.failure.loadBalancerCapabilities -ne $loadBalancerCapabilities){ + $DesiredConfigurationMatch = $false + Write-Verbose("loadBalancerCapabilities of AppPool $Name does not match the desired state."); + break + } + + #Check orphanWorkerProcess + if($PoolConfig.add.failure.orphanWorkerProcess -ne $orphanWorkerProcess){ + $DesiredConfigurationMatch = $false + Write-Verbose("orphanWorkerProcess of AppPool $Name does not match the desired state."); + break + } + + #Check orphanActionExe + if($PoolConfig.add.failure.orphanActionExe -ne $orphanActionExe){ + $DesiredConfigurationMatch = $false + Write-Verbose("orphanActionExe of AppPool $Name does not match the desired state."); + break + } + + #Check orphanActionParams + if($PoolConfig.add.failure.orphanActionParams -ne $orphanActionParams){ + $DesiredConfigurationMatch = $false + Write-Verbose("orphanActionParams of AppPool $Name does not match the desired state."); + break + } + + #Check rapidFailProtection + if($PoolConfig.add.failure.rapidFailProtection -ne $rapidFailProtection){ + $DesiredConfigurationMatch = $false + Write-Verbose("rapidFailProtection of AppPool $Name does not match the desired state."); + break + } + + #Check rapidFailProtectionInterval + if($PoolConfig.add.failure.rapidFailProtectionInterval -ne $rapidFailProtectionInterval){ + $DesiredConfigurationMatch = $false + Write-Verbose("rapidFailProtectionInterval of AppPool $Name does not match the desired state."); + break + } + + #Check rapidFailProtectionMaxCrashes + if($PoolConfig.add.failure.rapidFailProtectionMaxCrashes -ne $rapidFailProtectionMaxCrashes){ + $DesiredConfigurationMatch = $false + Write-Verbose("rapidFailProtectionMaxCrashes of AppPool $Name does not match the desired state."); + break + } + + #Check autoShutdownExe + if($PoolConfig.add.failure.autoShutdownExe -ne $autoShutdownExe){ + $DesiredConfigurationMatch = $false + Write-Verbose("autoShutdownExe of AppPool $Name does not match the desired state."); + break + } + + #Check autoShutdownParams + if($PoolConfig.add.failure.autoShutdownParams -ne $autoShutdownParams){ + $DesiredConfigurationMatch = $false + Write-Verbose("autoShutdownParams of AppPool $Name does not match the desired state."); + break + } + + #Check cpuLimit + if($PoolConfig.add.cpu.limit -ne $cpuLimit){ + $DesiredConfigurationMatch = $false + Write-Verbose("cpuLimit of AppPool $Name does not match the desired state."); + break + } + + #Check cpuAction + if($PoolConfig.add.cpu.action -ne $cpuAction){ + $DesiredConfigurationMatch = $false + Write-Verbose("cpuAction of AppPool $Name does not match the desired state."); + break + } + + #Check cpuResetInterval + if($PoolConfig.add.cpu.resetInterval -ne $cpuResetInterval){ + $DesiredConfigurationMatch = $false + Write-Verbose("cpuResetInterval of AppPool $Name does not match the desired state."); + break + } + + #Check cpuSmpAffinitized + if($PoolConfig.add.cpu.smpAffinitized -ne $cpuSmpAffinitized){ + $DesiredConfigurationMatch = $false + Write-Verbose("cpuSmpAffinitized of AppPool $Name does not match the desired state."); + break + } + + #Check cpuSmpProcessorAffinityMask + if($PoolConfig.add.cpu.smpProcessorAffinityMask -ne $cpuSmpProcessorAffinityMask){ + $DesiredConfigurationMatch = $false + Write-Verbose("cpuSmpProcessorAffinityMask of AppPool $Name does not match the desired state."); + break + } + + #Check cpuSmpProcessorAffinityMask2 + if($PoolConfig.add.cpu.smpProcessorAffinityMask2 -ne $cpuSmpProcessorAffinityMask2){ + $DesiredConfigurationMatch = $false + Write-Verbose("cpuSmpProcessorAffinityMask2 of AppPool $Name does not match the desired state."); + break + } + + } + + $Stop = $false + } + While($Stop) + + return $DesiredConfigurationMatch +} diff --git a/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.schema.mof b/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.schema.mof index b5bf7e46c..1a6de24be 100644 --- a/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.schema.mof +++ b/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.schema.mof @@ -1,12 +1,58 @@ -[ClassVersion("1.0.0.0"), FriendlyName("xWebAppPool")] +[ClassVersion("1.0.0.1"), FriendlyName("xWebAppPool")] class MSFT_xWebAppPool : OMI_BaseResource { [Key, Description("Name of the Web Application Pool")] String Name; [Write, Description("Web Application Pool Present/Absent"), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; - [Write, Description("State of Web Application Pool"), ValueMap{"Started","Stopped"}, Values{"Started","Stopped"}] String State; + [Write, Description("Should the app pool be started or stopped"), ValueMap{"Started","Stopped"}, Values{"Started","Stopped"}] String State; + [write, Description("When true, indicates to the World Wide Web Publishing Service (W3SVC) that the application pool should be automatically started when it is created or when IIS is started."), ValueMap{"true","false"},Values{"true","false"}] string autoStart; + [write, Description("Which version of .Net"), ValueMap{"v4.0","v2.0",""},Values{"v4.0","v2.0",""}] string managedRuntimeVersion; + [write, Description("Specifies the request-processing mode that is used to process requests for managed content."), ValueMap{"Integrated","Classic"},Values{"Integrated","Classic"}] string managedPipelineMode; + [write, Description("App pool always running or on demand"), ValueMap{"AlwaysRunning","OnDemand"},Values{"AlwaysRunning","OnDemand"}] string startMode; + + [write, Description("Who should the app pool run as"), ValueMap{"ApplicationPoolIdentity","LocalSystem","LocalService","NetworkService","SpecificUser"}, + Values{"ApplicationPoolIdentity","LocalSystem","LocalService","NetworkService","SpecificUser"}] + string identityType; + + [write, Description("User name if SpecificUser is choosen for app pool identity")] string userName; + [write, Description("Password of that user"), EmbeddedInstance("MSFT_Credential")] string Password; + [write, Description("Load the users profile"), ValueMap{"true","false"},Values{"true","false"}] string loadUserProfile; + [write, Description("Indicates to HTTP.sys how many requests to queue for an application pool before rejecting future requests.")] string queueLength; + [write, Description("When true, enables a 32-bit application to run on a computer that runs a 64-bit version of Windows."), ValueMap{"true","false"},Values{"true","false"}] string enable32BitAppOnWin64; + [write, Description("Specifies the managed loader to use for pre-loading the application pool.")] string managedRuntimeLoader; + [write, Description("When true, indicates that delegated settings in Web.config files will processed for applications within this application pool. When false, all settings in Web.config files will be ignored for this application pool."), ValueMap{"true","false"},Values{"true","false"}] string enableConfigurationOverride; + [write, Description("Specifies the .NET configuration file for the application pool.")] string CLRConfigFile; + [write, Description("If true, the Windows Process Activation Service (WAS) creates and passes a token for the built-in IUSR anonymous user account to the Anonymous authentication module. The Anonymous authentication module uses the token to impersonate the built-in account. When PassAnonymousToken is false, the token will not be passed."), ValueMap{"true","false"},Values{"true","false"}] string passAnonymousToken; + [write, Description("Specifies the logon type for the process identity."), ValueMap{"LogonBatch","LogonService"},Values{"LogonBatch","LogonService"}] string logonType; + [write, Description("Specifies whether the IIS_IUSRS group Security Identifier (SID) is added to the worker process token. When false, IIS automatically uses an application pool identity as though it were a member of the built-in IIS_IUSRS group, which has access to necessary file and system resources. When true, an application pool identity must be explicitly added to all resources that a worker process requires at runtime."), ValueMap{"true","false"},Values{"true","false"}] string manualGroupMembership; + [write, Description("The period of time a worker process should run if no new requests are received and the worker process is not processing requests.")] string idleTimeout; + [write, Description("The number of worker processes associated with the application pool.")] string maxProcesses; + [write, Description("The period of time that IIS waits for requests to finish running in a worker process before IIS terminates the worker process.")] string shutdownTimeLimit; + [write, Description("The period of time that IIS waits for an application pool to start.")] string startupTimeLimit; + [write, Description("Pinging behavior for the worker process health monitoring."), ValueMap{"true","false"},Values{"true","false"}] string pingingEnabled; + [write, Description("The time interval between health-monitoring pings that the World Wide Web Publishing Service (WWW service) sends to a worker process.")] string pingInterval; + [write, Description("The period of time that a worker process is given to respond to a health-monitoring ping.")] string pingResponseTime; + [write, Description("Specifies whether or not the World Wide Web Publishing Service (WWW Service) should start up another worker process to replace the existing worker process while it is shutting down."), ValueMap{"true","false"},Values{"true","false"}] string disallowOverlappingRotation; + [write, Description("Specifies whether the WWW Service should rotate worker processes in an application pool when the configuration has changed."), ValueMap{"true","false"},Values{"true","false"}] string disallowRotationOnConfigChange; + [write, Description("Specifies that IIS should log an event when an application pool is recycled. The logEventOnRecycle property must have a bit set corresponding to the reason for the recycle if IIS is to log the event.")] string logEventOnRecycle; + [write, Description("Restart app pool when memory exceeds this limit")] string restartMemoryLimit; + [write, Description("Restart app pool when private memory exceeds this limit")] string restartPrivateMemoryLimit; + [write, Description("Specifies that the worker process should be recycled after it processes a specific number of requests.")] string restartRequestsLimit; + [write, Description("Specifies that the worker process should be recycled after a specified amount of time has elapsed.")] string restartTimeLimit; + [write, Description("Restart the app pool at these times")] string restartSchedule[]; + [write, Description("The response behavior of a service when it is unavailable."), ValueMap{"HttpLevel","TcpLevel"},Values{"HttpLevel","TcpLevel"}] string loadBalancerCapabilities; + [write, Description("Value indicating whether to put a worker process in an orphan state when an application pool fails."), ValueMap{"true","false"},Values{"true","false"}] string orphanWorkerProcess; + [write, Description("The path of an executable to run when the service orphans a worker process.")] string orphanActionExe; + [write, Description("Command-line parameters for the executable named by the OrphanActionExe property.")] string orphanActionParams; + [write, Description("Value indicating whether rapid-fail protection is on or off."), ValueMap{"true","false"},Values{"true","false"}] string rapidFailProtection; + [write, Description("The interval of time before the failure count for a process is reset.")] string rapidFailProtectionInterval; + [write, Description("The maximum number of failures allowed within the time specified by the RapidFailProtectionInterval property.")] string rapidFailProtectionMaxCrashes; + [write, Description("The path of an executable to run when the service shuts down an application pool for rapid-fail protection.")] string autoShutdownExe; + [write, Description("Command-line parameters for the executable that is specified by the AutoShutdownExe property.")] string autoShutdownParams; + [write, Description("Configures the maximum percentage of CPU time (in 1/1000ths of one percent) that the worker processes in an application pool are allowed to consume over a period of time as indicated by the resetInterval attribute.")] string cpuLimit; + [write, Description("Configures the action that IIS takes when a worker process exceeds its configured CPU limit. "), ValueMap{"NoAction","KillW3wp","Throttle","ThrottleUnderLoad"},Values{"NoAction","KillW3wp","Throttle","ThrottleUnderLoad"}] string cpuAction; + [write, Description("Specifies the reset period (in minutes) for CPU monitoring and throttling limits on an application pool.")] string cpuResetInterval; + [write, Description("Specifies whether a particular worker process assigned to an application pool should also be assigned to a given CPU."), ValueMap{"true","false"},Values{"true","false"}] string cpuSmpAffinitized; + [write, Description("Specifies the hexadecimal processor mask for multi-processor computers, which indicates to which CPU the worker processes in an application pool should be bound. Before this property takes effect, the smpAffinitized attribute must be set to true for the application pool.")] string cpuSmpProcessorAffinityMask; + [write, Description("Specifies the high-order DWORD hexadecimal processor mask for 64-bit multi-processor computers, which indicates to which CPU the worker processes in an application pool should be bound. Before this property takes effect, the smpAffinitized attribute must be set to true for the application pool.")] string cpuSmpProcessorAffinityMask2; }; - - - - From 6c52cc752b3b550b09103ba8e8bf20fe4dbc1461 Mon Sep 17 00:00:00 2001 From: Aaron Zuehlke Date: Wed, 22 Apr 2015 11:13:02 -0500 Subject: [PATCH 2/9] Added xWebAppPool example --- Examples/Sample_xWebsite_NewWebsite.ps1 | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Examples/Sample_xWebsite_NewWebsite.ps1 b/Examples/Sample_xWebsite_NewWebsite.ps1 index 73edfa1a0..4f3c9aa19 100644 --- a/Examples/Sample_xWebsite_NewWebsite.ps1 +++ b/Examples/Sample_xWebsite_NewWebsite.ps1 @@ -61,6 +61,19 @@ configuration Sample_xWebsite_NewWebsite DependsOn = "[WindowsFeature]AspNet45" } + # Create the new AppPool + xWebAppPool NewAppPool + { + Name = $AppPoolName + Ensure = "Present" + autoStart = "true" + managedRuntimeVersion = "v4.0" + managedPipelineMode = "Integrated" + startMode = "AlwaysRunning" + identityType = "ApplicationPoolIdentity" + restartSchedule = @("18:30:00","05:00:00") + } + # Create the new Website xWebsite NewWebsite { From 298486e92bc11d2d13092ed07756f6d14e62ed22 Mon Sep 17 00:00:00 2001 From: Aaron Zuehlke Date: Wed, 22 Apr 2015 11:16:50 -0500 Subject: [PATCH 3/9] Added app pool parameter to the example --- Examples/Sample_xWebsite_NewWebsite.ps1 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Examples/Sample_xWebsite_NewWebsite.ps1 b/Examples/Sample_xWebsite_NewWebsite.ps1 index 4f3c9aa19..d1604b498 100644 --- a/Examples/Sample_xWebsite_NewWebsite.ps1 +++ b/Examples/Sample_xWebsite_NewWebsite.ps1 @@ -9,6 +9,11 @@ configuration Sample_xWebsite_NewWebsite [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [String]$WebSiteName, + + # Name of the app pool + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$AppPoolName, # Source Path for Website content [Parameter(Mandatory)] From bbcd73b5b1f33bfa42f4a05cdcac793e2b4139f3 Mon Sep 17 00:00:00 2001 From: Aaron Zuehlke Date: Thu, 25 Jun 2015 12:24:55 -0500 Subject: [PATCH 4/9] sample tests, making sure this is what is needed --- Tests/MSFT_xWebAppPool.Tests.ps1 | 78 ++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 Tests/MSFT_xWebAppPool.Tests.ps1 diff --git a/Tests/MSFT_xWebAppPool.Tests.ps1 b/Tests/MSFT_xWebAppPool.Tests.ps1 new file mode 100644 index 000000000..ae78428ce --- /dev/null +++ b/Tests/MSFT_xWebAppPool.Tests.ps1 @@ -0,0 +1,78 @@ +$here = Split-Path -Parent $MyInvocation.MyCommand.Path +$ModuleName = "MSFT_xWebAppPool" + +# Add web server if not already installed +if(!(Get-WindowsFeature web-server).Installed) +{ + Add-WindowsFeature Web-Server -Verbose +} + +Import-Module (Join-Path $here -ChildPath "..\DSCResources\$ModuleName\$ModuleName.psm1") + +if (! (Get-Module xDSCResourceDesigner)) +{ + Import-Module -Name xDSCResourceDesigner +} + +if (! (Get-Module WebAdministration)) +{ + Import-Module -Name WebAdministration +} + +Describe "MSFT_xWebAppPool"{ + InModuleScope $ModuleName { + $apName = "PesterAppPool" + + It 'Should pass Test-xDscResource Schema Validation' { + $result = Test-xDscResource MSFT_xWebAppPool + $result | Should Be $true + } + + It 'Should create a new App Pool' { + $testParams =@{ + Name = $apName + Ensure = "Present" + } + + # if the app pool exists, remove it + if((Get-ChildItem IIS:\apppools).Name.Contains($apName)) + { + Remove-WebAppPool -Name $apName -ErrorAction Stop + } + + Set-TargetResource @testParams + (Get-ChildItem IIS:\apppools).Name.Contains($apName) | Should be $true + } + + It 'Passes test when App Pool does exist'{ + $testParams =@{ + Name = $apName + Ensure = "Present" + } + + Mock -ModuleName $ModuleName Get-TargetResource { + return @{ + Name = $testParams.Name + Ensure = $testParams.Ensure + } + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails test when App Pool does not exist'{ + $testParams =@{ + Name = $apName + Ensure = "Present" + } + + # if the app pool exists, remove it + if((Get-ChildItem IIS:\apppools).Name.Contains($apName)) + { + Remove-WebAppPool -Name $apName -ErrorAction Stop + } + + Test-TargetResource @testParams | Should be $false + } + } +} \ No newline at end of file From d5eb0cda68b5bd2769b15436eb8b0502fdff8bbb Mon Sep 17 00:00:00 2001 From: Aaron Zuehlke Date: Thu, 25 Jun 2015 13:09:10 -0500 Subject: [PATCH 5/9] added some cleanup in finally and removed mock Get-TargetResource since Test-TargetResource doesn't use it --- Tests/MSFT_xWebAppPool.Tests.ps1 | 79 +++++++++++++++++--------------- 1 file changed, 42 insertions(+), 37 deletions(-) diff --git a/Tests/MSFT_xWebAppPool.Tests.ps1 b/Tests/MSFT_xWebAppPool.Tests.ps1 index ae78428ce..b9dff770e 100644 --- a/Tests/MSFT_xWebAppPool.Tests.ps1 +++ b/Tests/MSFT_xWebAppPool.Tests.ps1 @@ -21,58 +21,63 @@ if (! (Get-Module WebAdministration)) Describe "MSFT_xWebAppPool"{ InModuleScope $ModuleName { - $apName = "PesterAppPool" + try + { + $apName = "PesterAppPool" - It 'Should pass Test-xDscResource Schema Validation' { - $result = Test-xDscResource MSFT_xWebAppPool - $result | Should Be $true - } - - It 'Should create a new App Pool' { - $testParams =@{ - Name = $apName - Ensure = "Present" + It 'Should pass Test-xDscResource Schema Validation' { + $result = Test-xDscResource MSFT_xWebAppPool + $result | Should Be $true } - # if the app pool exists, remove it - if((Get-ChildItem IIS:\apppools).Name.Contains($apName)) - { - Remove-WebAppPool -Name $apName -ErrorAction Stop - } - - Set-TargetResource @testParams - (Get-ChildItem IIS:\apppools).Name.Contains($apName) | Should be $true - } + It 'Should create a new App Pool' { + $testParams =@{ + Name = $apName + Ensure = "Present" + } + + # if the app pool exists, remove it + if((Get-ChildItem IIS:\apppools).Name.Contains($apName)) + { + Remove-WebAppPool -Name $apName -ErrorAction Stop + } - It 'Passes test when App Pool does exist'{ - $testParams =@{ - Name = $apName - Ensure = "Present" + Set-TargetResource @testParams + (Get-ChildItem IIS:\apppools).Name.Contains($apName) | Should be $true } - Mock -ModuleName $ModuleName Get-TargetResource { - return @{ - Name = $testParams.Name - Ensure = $testParams.Ensure + It 'Passes test when App Pool does exist'{ + $testParams =@{ + Name = $apName + Ensure = "Present" } + + Test-TargetResource @testParams | Should be $true } - Test-TargetResource @testParams | Should be $true - } + It 'Fails test when App Pool does not exist'{ + $testParams =@{ + Name = $apName + Ensure = "Present" + } - It 'Fails test when App Pool does not exist'{ - $testParams =@{ - Name = $apName - Ensure = "Present" - } + # if the app pool exists, remove it + if((Get-ChildItem IIS:\apppools).Name.Contains($apName)) + { + Remove-WebAppPool -Name $apName -ErrorAction Stop + } + Test-TargetResource @testParams | Should be $false + } + } + finally + { # if the app pool exists, remove it if((Get-ChildItem IIS:\apppools).Name.Contains($apName)) { Remove-WebAppPool -Name $apName -ErrorAction Stop } - - Test-TargetResource @testParams | Should be $false } + } -} \ No newline at end of file +} From 2c3ff3ec9fa5d4cf46198791756fd3a9c0b38d68 Mon Sep 17 00:00:00 2001 From: Aaron Zuehlke Date: Thu, 25 Jun 2015 15:27:11 -0500 Subject: [PATCH 6/9] a few more tests --- Tests/MSFT_xWebAppPool.Tests.ps1 | 149 ++++++++++++++++++++++++++++++- 1 file changed, 148 insertions(+), 1 deletion(-) diff --git a/Tests/MSFT_xWebAppPool.Tests.ps1 b/Tests/MSFT_xWebAppPool.Tests.ps1 index b9dff770e..ba68d655b 100644 --- a/Tests/MSFT_xWebAppPool.Tests.ps1 +++ b/Tests/MSFT_xWebAppPool.Tests.ps1 @@ -24,6 +24,10 @@ Describe "MSFT_xWebAppPool"{ try { $apName = "PesterAppPool" + $baseParams =@{ + Name = $apName + Ensure = "Present" + } It 'Should pass Test-xDscResource Schema Validation' { $result = Test-xDscResource MSFT_xWebAppPool @@ -55,6 +59,150 @@ Describe "MSFT_xWebAppPool"{ Test-TargetResource @testParams | Should be $true } + It 'Should set autoStart' { + $testParams =@{ + Name = $apName + Ensure = "Present" + autoStart = "false" + } + + if(!([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.autoStart) + { + $testParams.autoStart = "true" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.autoStart -eq $testParams.autoStart | Should be $true + } + + It 'Passes autoStart Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + autoStart = "false" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.autoStart -eq "true") + { + $testParams.autoStart = "true" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails autoStart Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + autoStart = "false" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.autoStart -eq "false") + { + $testParams.autoStart = "true" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Runtime Version' { + $testParams =@{ + Name = $apName + Ensure = "Present" + managedRuntimeVersion = "v2.0" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.managedRuntimeVersion -eq "v2.0") + { + $testParams.managedRuntimeVersion = "v4.0" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.managedRuntimeVersion -eq $testParams.managedRuntimeVersion | Should be $true + } + + It 'Passes Runtime Version Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + managedRuntimeVersion = "v2.0" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.managedRuntimeVersion -eq "v4.0") + { + $testParams.managedRuntimeVersion = "v4.0" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Runtime Version Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + managedRuntimeVersion = "v2.0" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.managedRuntimeVersion -eq "v2.0") + { + $testParams.managedRuntimeVersion = "v4.0" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Managed Pipeline Mode Version' { + $testParams =@{ + Name = $apName + Ensure = "Present" + managedPipelineMode = "Classic" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.managedPipelineMode -eq "Classic") + { + $testParams.managedPipelineMode = "Integrated" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.managedPipelineMode -eq $testParams.managedPipelineMode | Should be $true + } + + It 'Passes Managed Pipeline Mode Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + managedPipelineMode = "Classic" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.managedPipelineMode -eq "Integrated") + { + $testParams.managedPipelineMode = "Integrated" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Managed Pipeline Mode Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + managedPipelineMode = "Classic" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.managedPipelineMode -eq "Classic") + { + $testParams.managedPipelineMode = "Integrated" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + It 'Fails test when App Pool does not exist'{ $testParams =@{ Name = $apName @@ -78,6 +226,5 @@ Describe "MSFT_xWebAppPool"{ Remove-WebAppPool -Name $apName -ErrorAction Stop } } - } } From 52fe42935d70676e76f48fc5b20cc00638dacccc Mon Sep 17 00:00:00 2001 From: Aaron Zuehlke Date: Wed, 29 Jul 2015 13:32:06 -0500 Subject: [PATCH 7/9] Now have total of 130 tests. Should cover 99% --- Tests/MSFT_xWebAppPool.Tests.ps1 | 1872 +++++++++++++++++++++++++++++- 1 file changed, 1871 insertions(+), 1 deletion(-) diff --git a/Tests/MSFT_xWebAppPool.Tests.ps1 b/Tests/MSFT_xWebAppPool.Tests.ps1 index ba68d655b..5b00b90a0 100644 --- a/Tests/MSFT_xWebAppPool.Tests.ps1 +++ b/Tests/MSFT_xWebAppPool.Tests.ps1 @@ -200,8 +200,1878 @@ Describe "MSFT_xWebAppPool"{ Test-TargetResource @testParams | Should be $false } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Start Mode' { + $testParams =@{ + Name = $apName + Ensure = "Present" + startMode = "OnDemand" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.startMode -eq "OnDemand") + { + $testParams.startMode = "AlwaysRunning" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.startMode -eq $testParams.startMode | Should be $true + } + + It 'Passes Start Mode Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + startMode = "OnDemand" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.startMode -eq "AlwaysRunning") + { + $testParams.startMode = "AlwaysRunning" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Start Mode Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + startMode = "OnDemand" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.startMode -eq "OnDemand") + { + $testParams.startMode = "AlwaysRunning" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Identity Type' { + $testParams =@{ + Name = $apName + Ensure = "Present" + identityType = "LocalSystem" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.identityType -eq "LocalSystem") + { + $testParams.identityType = "ApplicationPoolIdentity" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.identityType -eq $testParams.identityType | Should be $true + } + + It 'Passes Identity Type Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + identityType = "LocalSystem" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.identityType -eq "ApplicationPoolIdentity") + { + $testParams.identityType = "ApplicationPoolIdentity" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Identity Type Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + identityType = "LocalSystem" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.identityType -eq "LocalSystem") + { + $testParams.identityType = "ApplicationPoolIdentity" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Load User Profile' { + $testParams =@{ + Name = $apName + Ensure = "Present" + loadUserProfile = "false" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.loadUserProfile -eq "false") + { + $testParams.loadUserProfile = "true" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.loadUserProfile -eq $testParams.loadUserProfile | Should be $true + } + + It 'Passes Load User Profile Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + loadUserProfile = "false" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.loadUserProfile -eq "true") + { + $testParams.loadUserProfile = "true" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Load User Profile Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + loadUserProfile = "false" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.loadUserProfile -eq "false") + { + $testParams.loadUserProfile = "true" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Queue Length' { + $testParams =@{ + Name = $apName + Ensure = "Present" + queueLength = "2000" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.queueLength -eq "2000") + { + $testParams.loadUserProfile = "1000" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.queueLength -eq $testParams.queueLength | Should be $true + } + + It 'Passes Queue Length Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + queueLength = "2000" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.queueLength -eq "1000") + { + $testParams.queueLength = "1000" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Queue Length Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + queueLength = "2000" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.queueLength -eq "2000") + { + $testParams.queueLength = "1000" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Enable 32bit' { + $testParams =@{ + Name = $apName + Ensure = "Present" + enable32BitAppOnWin64 = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.enable32BitAppOnWin64 -eq "true") + { + $testParams.enable32BitAppOnWin64 = "false" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.enable32BitAppOnWin64 -eq $testParams.enable32BitAppOnWin64 | Should be $true + } + + It 'Passes Enable 32bit Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + enable32BitAppOnWin64 = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.enable32BitAppOnWin64 -eq "false") + { + $testParams.enable32BitAppOnWin64 = "false" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Enable 32bit Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + enable32BitAppOnWin64 = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.enable32BitAppOnWin64 -eq "true") + { + $testParams.enable32BitAppOnWin64 = "false" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Config Override' { + $testParams =@{ + Name = $apName + Ensure = "Present" + enableConfigurationOverride = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.enableConfigurationOverride -eq "true") + { + $testParams.enableConfigurationOverride = "false" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.enableConfigurationOverride -eq $testParams.enableConfigurationOverride | Should be $true + } + + It 'Passes Config Override Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + enableConfigurationOverride = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.enableConfigurationOverride -eq "false") + { + $testParams.enableConfigurationOverride = "false" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Config Override Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + enableConfigurationOverride = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.enableConfigurationOverride -eq "true") + { + $testParams.enableConfigurationOverride = "false" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Pass Anon Token' { + $testParams =@{ + Name = $apName + Ensure = "Present" + passAnonymousToken = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.passAnonymousToken -eq "true") + { + $testParams.passAnonymousToken = "false" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.passAnonymousToken -eq $testParams.passAnonymousToken | Should be $true + } + + It 'Passes Pass Anon Token Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + passAnonymousToken = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.passAnonymousToken -eq "false") + { + $testParams.passAnonymousToken = "false" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Pass Anon Token Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + passAnonymousToken = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.passAnonymousToken -eq "true") + { + $testParams.passAnonymousToken = "false" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Logon Type' { + $testParams =@{ + Name = $apName + Ensure = "Present" + logonType = "LogonService" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.logonType -eq "LogonService") + { + $testParams.logonType = "LogonBatch" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.logonType -eq $testParams.logonType | Should be $true + } + + It 'Passes Logon Type Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + logonType = "LogonService" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.logonType -eq "LogonBatch") + { + $testParams.logonType = "LogonBatch" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Logon Type Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + logonType = "LogonService" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.logonType -eq "LogonService") + { + $testParams.logonType = "LogonBatch" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Manual Group Membership' { + $testParams =@{ + Name = $apName + Ensure = "Present" + manualGroupMembership = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.manualGroupMembership -eq "true") + { + $testParams.manualGroupMembership = "false" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.manualGroupMembership -eq $testParams.manualGroupMembership | Should be $true + } + + It 'Passes Manual Group Membership Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + manualGroupMembership = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.manualGroupMembership -eq "false") + { + $testParams.manualGroupMembership = "false" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Manual Group Membership Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + manualGroupMembership = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.manualGroupMembership -eq "true") + { + $testParams.manualGroupMembership = "false" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Idle Timeout' { + $testParams =@{ + Name = $apName + Ensure = "Present" + idleTimeout = "00:25:00" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.idleTimeout -eq "00:25:00") + { + $testParams.idleTimeout = "00:20:00" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.idleTimeout -eq $testParams.idleTimeout | Should be $true + } + + It 'Passes Idle Timeout Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + idleTimeout = "00:25:00" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.idleTimeout -eq "00:20:00") + { + $testParams.idleTimeout = "00:20:00" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Idle Timeout Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + idleTimeout = "00:25:00" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.idleTimeout -eq "00:25:00") + { + $testParams.idleTimeout = "00:20:00" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Max Processes' { + $testParams =@{ + Name = $apName + Ensure = "Present" + maxProcesses = "2" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.maxProcesses -eq "2") + { + $testParams.maxProcesses = "1" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.maxProcesses -eq $testParams.maxProcesses | Should be $true + } + + It 'Passes Max Processes Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + maxProcesses = "2" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.maxProcesses -eq "1") + { + $testParams.maxProcesses = "1" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Max Processes Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + maxProcesses = "2" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.maxProcesses -eq "2") + { + $testParams.maxProcesses = "1" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Shutdown Time Limit' { + $testParams =@{ + Name = $apName + Ensure = "Present" + shutdownTimeLimit = "00:02:30" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.shutdownTimeLimit -eq "00:02:30") + { + $testParams.shutdownTimeLimit = "00:01:30" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.shutdownTimeLimit -eq $testParams.shutdownTimeLimit | Should be $true + } + + It 'Passes Shutdown Time Limit Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + shutdownTimeLimit = "00:02:30" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.shutdownTimeLimit -eq "00:01:30") + { + $testParams.shutdownTimeLimit = "00:01:30" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Shutdown Time Limit Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + shutdownTimeLimit = "00:02:30" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.shutdownTimeLimit -eq "00:02:30") + { + $testParams.shutdownTimeLimit = "00:01:30" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Startup Time Limit' { + $testParams =@{ + Name = $apName + Ensure = "Present" + startupTimeLimit = "00:02:30" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.startupTimeLimit -eq "00:02:30") + { + $testParams.startupTimeLimit = "00:01:30" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.startupTimeLimit -eq $testParams.startupTimeLimit | Should be $true + } + + It 'Passes Startup Time Limit Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + startupTimeLimit = "00:02:30" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.startupTimeLimit -eq "00:01:30") + { + $testParams.startupTimeLimit = "00:01:30" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Startup Time Limit Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + startupTimeLimit = "00:02:30" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.startupTimeLimit -eq "00:02:30") + { + $testParams.startupTimeLimit = "00:01:30" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Ping Interval' { + $testParams =@{ + Name = $apName + Ensure = "Present" + pingInterval = "00:02:30" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingInterval -eq "00:02:30") + { + $testParams.pingInterval = "00:01:30" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingInterval -eq $testParams.pingInterval | Should be $true + } + + It 'Passes Ping Interval Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + pingInterval = "00:02:30" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingInterval -eq "00:01:30") + { + $testParams.pingInterval = "00:01:30" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Ping Interval Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + pingInterval = "00:02:30" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingInterval -eq "00:02:30") + { + $testParams.pingInterval = "00:01:30" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Ping Response Time' { + $testParams =@{ + Name = $apName + Ensure = "Present" + pingResponseTime = "00:02:30" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingResponseTime -eq "00:02:30") + { + $testParams.pingResponseTime = "00:01:30" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingResponseTime -eq $testParams.pingResponseTime | Should be $true + } + + It 'Passes Ping Response Time Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + pingResponseTime = "00:02:30" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingResponseTime -eq "00:01:30") + { + $testParams.pingResponseTime = "00:01:30" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Ping Response Time Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + pingResponseTime = "00:02:30" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingResponseTime -eq "00:02:30") + { + $testParams.pingResponseTime = "00:01:30" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Ping Enabled' { + $testParams =@{ + Name = $apName + Ensure = "Present" + pingingEnabled = "false" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingingEnabled -eq "false") + { + $testParams.pingingEnabled = "true" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingingEnabled -eq $testParams.pingingEnabled | Should be $true + } + + It 'Passes Ping Enabled Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + pingingEnabled = "false" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingingEnabled -eq "true") + { + $testParams.pingingEnabled = "true" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Ping Enabled Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + pingingEnabled = "false" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingingEnabled -eq "false") + { + $testParams.pingingEnabled = "true" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Disallow Overlapping Rotation' { + $testParams =@{ + Name = $apName + Ensure = "Present" + disallowOverlappingRotation = "false" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.disallowOverlappingRotation -eq "false") + { + $testParams.disallowOverlappingRotation = "true" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.disallowOverlappingRotation -eq $testParams.disallowOverlappingRotation | Should be $true + } + + It 'Passes Disallow Overlapping Rotation Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + disallowOverlappingRotation = "false" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.disallowOverlappingRotation -eq "true") + { + $testParams.disallowOverlappingRotation = "true" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Disallow Overlapping Rotation Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + disallowOverlappingRotation = "false" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.disallowOverlappingRotation -eq "false") + { + $testParams.disallowOverlappingRotation = "true" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Disallow Rotation On Config Change' { + $testParams =@{ + Name = $apName + Ensure = "Present" + disallowRotationOnConfigChange = "false" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.disallowRotationOnConfigChange -eq "false") + { + $testParams.disallowRotationOnConfigChange = "true" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.disallowRotationOnConfigChange -eq $testParams.disallowRotationOnConfigChange | Should be $true + } + + It 'Passes Disallow Rotation On Config Change Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + disallowRotationOnConfigChange = "false" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.disallowRotationOnConfigChange -eq "true") + { + $testParams.disallowRotationOnConfigChange = "true" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Disallow Rotation On Config Change Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + disallowRotationOnConfigChange = "false" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.disallowRotationOnConfigChange -eq "false") + { + $testParams.disallowRotationOnConfigChange = "true" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Log Event On Recycle' { + $testParams =@{ + Name = $apName + Ensure = "Present" + logEventOnRecycle = "Time, Memory" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.logEventOnRecycle -eq "Time, Memory") + { + $testParams.logEventOnRecycle = "Time, Memory, PrivateMemory" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.logEventOnRecycle -eq $testParams.logEventOnRecycle | Should be $true + } + + It 'Passes Log Event On Recycle Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + logEventOnRecycle = "Time, Memory" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.logEventOnRecycle -eq "Time, Memory, PrivateMemory") + { + $testParams.logEventOnRecycle = "Time, Memory, PrivateMemory" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Log Event On Recycle Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + logEventOnRecycle = "Time, Memory" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.logEventOnRecycle -eq "Time, Memory") + { + $testParams.logEventOnRecycle = "Time, Memory, PrivateMemory" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Restart Mem Limit' { + $testParams =@{ + Name = $apName + Ensure = "Present" + restartMemoryLimit = "1" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.memory -eq "1") + { + $testParams.restartMemoryLimit = "0" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.memory -eq $testParams.restartMemoryLimit | Should be $true + } + + It 'Passes Restart Mem Limit Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + restartMemoryLimit = "1" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.memory -eq "0") + { + $testParams.restartMemoryLimit = "0" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Restart Mem Limit Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + restartMemoryLimit = "1" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.memory -eq "1") + { + $testParams.restartMemoryLimit = "0" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Restart Private Mem Limit' { + $testParams =@{ + Name = $apName + Ensure = "Present" + restartPrivateMemoryLimit = "1" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.privateMemory -eq "1") + { + $testParams.restartPrivateMemoryLimit = "0" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.privateMemory -eq $testParams.restartPrivateMemoryLimit | Should be $true + } + + It 'Passes Restart Private Mem Limit Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + restartPrivateMemoryLimit = "1" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.privateMemory -eq "0") + { + $testParams.restartPrivateMemoryLimit = "0" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Restart Private Mem Limit Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + restartPrivateMemoryLimit = "1" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.privateMemory -eq "1") + { + $testParams.restartPrivateMemoryLimit = "0" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Restart Requests Limit' { + $testParams =@{ + Name = $apName + Ensure = "Present" + restartRequestsLimit = "1" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.requests -eq "1") + { + $testParams.restartRequestsLimit = "0" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.requests -eq $testParams.restartRequestsLimit | Should be $true + } + + It 'Passes Restart Requests Limit Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + restartRequestsLimit = "1" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.requests -eq "0") + { + $testParams.restartRequestsLimit = "0" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Restart Requests Limit Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + restartRequestsLimit = "1" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.requests -eq "1") + { + $testParams.restartRequestsLimit = "0" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Restart Time Limit' { + $testParams =@{ + Name = $apName + Ensure = "Present" + restartTimeLimit = "2.05:00:00" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.time -eq "2.05:00:00") + { + $testParams.restartTimeLimit = "1.05:00:00" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.time -eq $testParams.restartTimeLimit | Should be $true + } + + It 'Passes Restart Time Limit Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + restartTimeLimit = "2.05:00:00" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.time -eq "1.05:00:00") + { + $testParams.restartTimeLimit = "1.05:00:00" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Restart Time Limit Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + restartTimeLimit = "2.05:00:00" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.time -eq "2.05:00:00") + { + $testParams.restartTimeLimit = "1.05:00:00" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Restart Schedule' { + $testParams =@{ + Name = $apName + Ensure = "Present" + restartSchedule = "18:30:00" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.schedule.add.value -eq "18:30:00") + { + $testParams.restartSchedule = "10:30:00" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.schedule.add.value -eq $testParams.restartSchedule | Should be $true + } + + It 'Passes Restart Schedule Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + restartSchedule = "18:30:00" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.schedule.add.value -eq "10:30:00") + { + $testParams.restartSchedule = "10:30:00" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Restart Schedule Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + restartSchedule = "18:30:00" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.schedule.add.value -eq "18:30:00") + { + $testParams.restartSchedule = "10:30:00" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Load Balancer Capabilities' { + $testParams =@{ + Name = $apName + Ensure = "Present" + loadBalancerCapabilities = "TcpLevel" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.loadBalancerCapabilities -eq "TcpLevel") + { + $testParams.loadBalancerCapabilities = "HttpLevel" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.loadBalancerCapabilities -eq $testParams.loadBalancerCapabilities | Should be $true + } + + It 'Passes Load Balancer Capabilities Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + loadBalancerCapabilities = "TcpLevel" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.loadBalancerCapabilities -eq "HttpLevel") + { + $testParams.loadBalancerCapabilities = "HttpLevel" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Load Balancer Capabilities Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + loadBalancerCapabilities = "TcpLevel" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.loadBalancerCapabilities -eq "TcpLevel") + { + $testParams.loadBalancerCapabilities = "HttpLevel" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Orphan Worker Process' { + $testParams =@{ + Name = $apName + Ensure = "Present" + orphanWorkerProcess = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanWorkerProcess -eq "true") + { + $testParams.orphanWorkerProcess = "false" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanWorkerProcess -eq $testParams.orphanWorkerProcess | Should be $true + } + + It 'Passes Orphan Worker Process Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + orphanWorkerProcess = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanWorkerProcess -eq "false") + { + $testParams.orphanWorkerProcess = "false" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Orphan Worker Process Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + orphanWorkerProcess = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanWorkerProcess -eq "true") + { + $testParams.orphanWorkerProcess = "false" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Orphan Action Exe' { + $testParams =@{ + Name = $apName + Ensure = "Present" + orphanActionExe = "test.exe" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanActionExe -eq "test.exe") + { + $testParams.orphanActionExe = "test1.exe" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanActionExe -eq $testParams.orphanActionExe | Should be $true + } + + It 'Passes Orphan Action Exe Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + orphanActionExe = "test.exe" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanActionExe -eq "test1.exe") + { + $testParams.orphanActionExe = "test1.exe" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Orphan Action Exe Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + orphanActionExe = "test.exe" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanActionExe -eq "test.exe") + { + $testParams.orphanActionExe = "test1.exe" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Orphan Action Params' { + $testParams =@{ + Name = $apName + Ensure = "Present" + orphanActionParams = "test.exe" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanActionParams -eq "test.exe") + { + $testParams.orphanActionParams = "test1.exe" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanActionParams -eq $testParams.orphanActionParams | Should be $true + } + + It 'Passes Orphan Action Params Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + orphanActionParams = "test.exe" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanActionParams -eq "test1.exe") + { + $testParams.orphanActionParams = "test1.exe" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Orphan Action Params Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + orphanActionParams = "test.exe" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanActionParams -eq "test.exe") + { + $testParams.orphanActionParams = "test1.exe" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Rapid Fail Protection' { + $testParams =@{ + Name = $apName + Ensure = "Present" + rapidFailProtection = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtection -eq "true") + { + $testParams.rapidFailProtection = "false" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtection -eq $testParams.rapidFailProtection | Should be $true + } + + It 'Passes Rapid Fail Protection Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + rapidFailProtection = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtection -eq "false") + { + $testParams.rapidFailProtection = "false" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Rapid Fail Protection Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + rapidFailProtection = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtection -eq "true") + { + $testParams.rapidFailProtection = "false" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Rapid Fail Protection Interval' { + $testParams =@{ + Name = $apName + Ensure = "Present" + rapidFailProtectionInterval = "00:15:00" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtectionInterval -eq "00:15:00") + { + $testParams.rapidFailProtectionInterval = "00:05:00" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtectionInterval -eq $testParams.rapidFailProtectionInterval | Should be $true + } + + It 'Passes Rapid Fail Protection Interval Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + rapidFailProtectionInterval = "00:15:00" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtectionInterval -eq "00:05:00") + { + $testParams.rapidFailProtectionInterval = "00:05:00" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Rapid Fail Protection Interval Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + rapidFailProtectionInterval = "00:15:00" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtectionInterval -eq "00:15:00") + { + $testParams.rapidFailProtectionInterval = "00:05:00" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Rapid Fail Protection Max Crashes' { + $testParams =@{ + Name = $apName + Ensure = "Present" + rapidFailProtectionMaxCrashes = "15" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtectionMaxCrashes -eq "15") + { + $testParams.rapidFailProtectionMaxCrashes = "05" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtectionMaxCrashes -eq $testParams.rapidFailProtectionMaxCrashes | Should be $true + } + + It 'Passes Rapid Fail Protection Interval Max Crashes when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + rapidFailProtectionMaxCrashes = "15" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtectionMaxCrashes -eq "05") + { + $testParams.rapidFailProtectionMaxCrashes = "05" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Rapid Fail Protection Max Crashes Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + rapidFailProtectionMaxCrashes = "15" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtectionMaxCrashes -eq "15") + { + $testParams.rapidFailProtectionMaxCrashes = "05" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Auto Shutdown Exe' { + $testParams =@{ + Name = $apName + Ensure = "Present" + autoShutdownExe = "test.exe" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.autoShutdownExe -eq "test.exe") + { + $testParams.autoShutdownExe = "test1.exe" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.autoShutdownExe -eq $testParams.autoShutdownExe | Should be $true + } + + It 'Passes Auto Shutdown Exe Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + autoShutdownExe = "test.exe" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.autoShutdownExe -eq "test1.exe") + { + $testParams.autoShutdownExe = "test1.exe" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Auto Shutdown Exe Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + autoShutdownExe = "test.exe" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.autoShutdownExe -eq "test.exe") + { + $testParams.autoShutdownExe = "test1.exe" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set Auto Shutdown Params' { + $testParams =@{ + Name = $apName + Ensure = "Present" + autoShutdownParams = "test.exe" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.autoShutdownParams -eq "test.exe") + { + $testParams.autoShutdownParams = "test1.exe" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.autoShutdownParams -eq $testParams.autoShutdownParams | Should be $true + } + + It 'Passes Auto Shutdown Params Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + autoShutdownParams = "test.exe" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.autoShutdownParams -eq "test1.exe") + { + $testParams.autoShutdownParams = "test1.exe" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails Auto Shutdown Params Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + autoShutdownParams = "test.exe" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.autoShutdownParams -eq "test.exe") + { + $testParams.autoShutdownParams = "test1.exe" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set CPU Limit' { + $testParams =@{ + Name = $apName + Ensure = "Present" + cpuLimit = "1" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.limit -eq "1") + { + $testParams.cpuLimit = "0" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.limit -eq $testParams.cpuLimit | Should be $true + } + + It 'Passes CPU Limit Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + cpuLimit = "1" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.limit -eq "0") + { + $testParams.cpuLimit = "0" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails CPU Limit Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + cpuLimit = "1" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.limit -eq "1") + { + $testParams.cpuLimit = "0" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set CPU Action' { + $testParams =@{ + Name = $apName + Ensure = "Present" + cpuAction = "Throttle" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.action -eq "Throttle") + { + $testParams.cpuAction = "NoAction" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.action -eq $testParams.cpuAction | Should be $true + } + + It 'Passes CPU Action Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + cpuAction = "Throttle" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.action -eq "NoAction") + { + $testParams.cpuAction = "NoAction" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails CPU Action Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + cpuAction = "Throttle" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.action -eq "Throttle") + { + $testParams.cpuAction = "NoAction" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set CPU Reset Interval' { + $testParams =@{ + Name = $apName + Ensure = "Present" + cpuResetInterval = "00:15:00" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.resetInterval -eq "00:15:00") + { + $testParams.cpuResetInterval = "00:05:00" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.resetInterval -eq $testParams.cpuResetInterval | Should be $true + } + + It 'Passes CPU Reset Interval Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + cpuResetInterval = "00:15:00" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.resetInterval -eq "00:05:00") + { + $testParams.cpuResetInterval = "00:05:00" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails CPU Reset Interval Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + cpuResetInterval = "00:15:00" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.resetInterval -eq "00:15:00") + { + $testParams.cpuResetInterval = "00:05:00" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set CPU Smp Affinitized' { + $testParams =@{ + Name = $apName + Ensure = "Present" + cpuSmpAffinitized = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpAffinitized -eq "true") + { + $testParams.cpuSmpAffinitized = "false" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpAffinitized -eq $testParams.cpuSmpAffinitized | Should be $true + } + + It 'Passes CPU Smp Affinitized Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + cpuSmpAffinitized = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpAffinitized -eq "false") + { + $testParams.cpuSmpAffinitized = "false" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails CPU Smp Affinitized Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + cpuSmpAffinitized = "true" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpAffinitized -eq "true") + { + $testParams.cpuSmpAffinitized = "false" + } + + Test-TargetResource @testParams | Should be $false + } + + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + It 'Should set CPU Smp Processor Affinity Mask' { + $testParams =@{ + Name = $apName + Ensure = "Present" + cpuSmpProcessorAffinityMask = "4294967294" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpProcessorAffinityMask -eq "4294967294") + { + $testParams.cpuSmpProcessorAffinityMask = "4294967295" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpProcessorAffinityMask -eq $testParams.cpuSmpProcessorAffinityMask | Should be $true + } + + It 'Passes CPU Smp Processor Affinity Mask Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + cpuSmpProcessorAffinityMask = "4294967294" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpProcessorAffinityMask -eq "4294967295") + { + $testParams.cpuSmpProcessorAffinityMask = "4294967295" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails CPU Smp Processor Affinity Mask Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + cpuSmpProcessorAffinityMask = "4294967294" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpProcessorAffinityMask -eq "4294967294") + { + $testParams.cpuSmpProcessorAffinityMask = "4294967295" + } + + Test-TargetResource @testParams | Should be $false + } + Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + + It 'Should set CPU Smp Processor Affinity Mask 2' { + $testParams =@{ + Name = $apName + Ensure = "Present" + cpuSmpProcessorAffinityMask2 = "4294967294" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpProcessorAffinityMask2 -eq "4294967294") + { + $testParams.cpuSmpProcessorAffinityMask2 = "4294967295" + } + + Set-TargetResource @testParams + ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpProcessorAffinityMask2 -eq $testParams.cpuSmpProcessorAffinityMask2 | Should be $true + } + + It 'Passes CPU Smp Processor Affinity Mask 2 Test when same' { + $testParams =@{ + Name = $apName + Ensure = "Present" + cpuSmpProcessorAffinityMask2 = "4294967294" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpProcessorAffinityMask2 -eq "4294967295") + { + $testParams.cpuSmpProcessorAffinityMask2 = "4294967295" + } + + Test-TargetResource @testParams | Should be $true + } + + It 'Fails CPU Smp Processor Affinity Mask 2 Test when different' { + $testParams =@{ + Name = $apName + Ensure = "Present" + cpuSmpProcessorAffinityMask2 = "4294967294" + } + + if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpProcessorAffinityMask2 -eq "4294967294") + { + $testParams.cpuSmpProcessorAffinityMask2 = "4294967295" + } + + Test-TargetResource @testParams | Should be $false + } It 'Fails test when App Pool does not exist'{ $testParams =@{ @@ -225,6 +2095,6 @@ Describe "MSFT_xWebAppPool"{ { Remove-WebAppPool -Name $apName -ErrorAction Stop } - } + } } } From 89be13a4e5d1266e9679fcd5ea8a5861607130f7 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 12 Aug 2015 12:58:44 -0500 Subject: [PATCH 8/9] Separated Test and Set into different Contexts. Refactored to make future tests simpler to add --- Tests/MSFT_xWebAppPool.Tests.ps1 | 2494 ++++++++---------------------- 1 file changed, 621 insertions(+), 1873 deletions(-) diff --git a/Tests/MSFT_xWebAppPool.Tests.ps1 b/Tests/MSFT_xWebAppPool.Tests.ps1 index 5b00b90a0..cf0d5d2da 100644 --- a/Tests/MSFT_xWebAppPool.Tests.ps1 +++ b/Tests/MSFT_xWebAppPool.Tests.ps1 @@ -21,2061 +21,809 @@ if (! (Get-Module WebAdministration)) Describe "MSFT_xWebAppPool"{ InModuleScope $ModuleName { - try - { - $apName = "PesterAppPool" - $baseParams =@{ - Name = $apName - Ensure = "Present" - } - - It 'Should pass Test-xDscResource Schema Validation' { - $result = Test-xDscResource MSFT_xWebAppPool - $result | Should Be $true - } - - It 'Should create a new App Pool' { - $testParams =@{ - Name = $apName - Ensure = "Present" - } - - # if the app pool exists, remove it - if((Get-ChildItem IIS:\apppools).Name.Contains($apName)) - { - Remove-WebAppPool -Name $apName -ErrorAction Stop - } - - Set-TargetResource @testParams - (Get-ChildItem IIS:\apppools).Name.Contains($apName) | Should be $true - } - - It 'Passes test when App Pool does exist'{ - $testParams =@{ - Name = $apName - Ensure = "Present" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Should set autoStart' { - $testParams =@{ - Name = $apName - Ensure = "Present" - autoStart = "false" - } - - if(!([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.autoStart) - { - $testParams.autoStart = "true" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.autoStart -eq $testParams.autoStart | Should be $true - } - - It 'Passes autoStart Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - autoStart = "false" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.autoStart -eq "true") - { - $testParams.autoStart = "true" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails autoStart Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - autoStart = "false" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.autoStart -eq "false") - { - $testParams.autoStart = "true" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Runtime Version' { - $testParams =@{ - Name = $apName - Ensure = "Present" - managedRuntimeVersion = "v2.0" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.managedRuntimeVersion -eq "v2.0") - { - $testParams.managedRuntimeVersion = "v4.0" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.managedRuntimeVersion -eq $testParams.managedRuntimeVersion | Should be $true - } - - It 'Passes Runtime Version Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - managedRuntimeVersion = "v2.0" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.managedRuntimeVersion -eq "v4.0") - { - $testParams.managedRuntimeVersion = "v4.0" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Runtime Version Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - managedRuntimeVersion = "v2.0" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.managedRuntimeVersion -eq "v2.0") - { - $testParams.managedRuntimeVersion = "v4.0" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Managed Pipeline Mode Version' { - $testParams =@{ - Name = $apName - Ensure = "Present" - managedPipelineMode = "Classic" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.managedPipelineMode -eq "Classic") - { - $testParams.managedPipelineMode = "Integrated" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.managedPipelineMode -eq $testParams.managedPipelineMode | Should be $true - } - - It 'Passes Managed Pipeline Mode Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - managedPipelineMode = "Classic" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.managedPipelineMode -eq "Integrated") - { - $testParams.managedPipelineMode = "Integrated" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Managed Pipeline Mode Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - managedPipelineMode = "Classic" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.managedPipelineMode -eq "Classic") - { - $testParams.managedPipelineMode = "Integrated" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Start Mode' { - $testParams =@{ - Name = $apName - Ensure = "Present" - startMode = "OnDemand" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.startMode -eq "OnDemand") - { - $testParams.startMode = "AlwaysRunning" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.startMode -eq $testParams.startMode | Should be $true - } - - It 'Passes Start Mode Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - startMode = "OnDemand" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.startMode -eq "AlwaysRunning") - { - $testParams.startMode = "AlwaysRunning" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Start Mode Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - startMode = "OnDemand" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.startMode -eq "OnDemand") - { - $testParams.startMode = "AlwaysRunning" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Identity Type' { - $testParams =@{ - Name = $apName - Ensure = "Present" - identityType = "LocalSystem" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.identityType -eq "LocalSystem") - { - $testParams.identityType = "ApplicationPoolIdentity" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.identityType -eq $testParams.identityType | Should be $true - } - - It 'Passes Identity Type Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - identityType = "LocalSystem" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.identityType -eq "ApplicationPoolIdentity") - { - $testParams.identityType = "ApplicationPoolIdentity" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Identity Type Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - identityType = "LocalSystem" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.identityType -eq "LocalSystem") - { - $testParams.identityType = "ApplicationPoolIdentity" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Load User Profile' { - $testParams =@{ - Name = $apName - Ensure = "Present" - loadUserProfile = "false" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.loadUserProfile -eq "false") - { - $testParams.loadUserProfile = "true" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.loadUserProfile -eq $testParams.loadUserProfile | Should be $true - } - - It 'Passes Load User Profile Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - loadUserProfile = "false" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.loadUserProfile -eq "true") - { - $testParams.loadUserProfile = "true" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Load User Profile Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - loadUserProfile = "false" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.loadUserProfile -eq "false") - { - $testParams.loadUserProfile = "true" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Queue Length' { - $testParams =@{ - Name = $apName - Ensure = "Present" - queueLength = "2000" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.queueLength -eq "2000") - { - $testParams.loadUserProfile = "1000" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.queueLength -eq $testParams.queueLength | Should be $true - } - - It 'Passes Queue Length Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - queueLength = "2000" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.queueLength -eq "1000") - { - $testParams.queueLength = "1000" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Queue Length Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - queueLength = "2000" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.queueLength -eq "2000") - { - $testParams.queueLength = "1000" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Enable 32bit' { - $testParams =@{ - Name = $apName - Ensure = "Present" - enable32BitAppOnWin64 = "true" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.enable32BitAppOnWin64 -eq "true") - { - $testParams.enable32BitAppOnWin64 = "false" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.enable32BitAppOnWin64 -eq $testParams.enable32BitAppOnWin64 | Should be $true - } - - It 'Passes Enable 32bit Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - enable32BitAppOnWin64 = "true" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.enable32BitAppOnWin64 -eq "false") - { - $testParams.enable32BitAppOnWin64 = "false" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Enable 32bit Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - enable32BitAppOnWin64 = "true" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.enable32BitAppOnWin64 -eq "true") - { - $testParams.enable32BitAppOnWin64 = "false" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Config Override' { - $testParams =@{ - Name = $apName - Ensure = "Present" - enableConfigurationOverride = "true" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.enableConfigurationOverride -eq "true") - { - $testParams.enableConfigurationOverride = "false" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.enableConfigurationOverride -eq $testParams.enableConfigurationOverride | Should be $true - } - - It 'Passes Config Override Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - enableConfigurationOverride = "true" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.enableConfigurationOverride -eq "false") - { - $testParams.enableConfigurationOverride = "false" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Config Override Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - enableConfigurationOverride = "true" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.enableConfigurationOverride -eq "true") - { - $testParams.enableConfigurationOverride = "false" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Pass Anon Token' { - $testParams =@{ - Name = $apName - Ensure = "Present" - passAnonymousToken = "true" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.passAnonymousToken -eq "true") - { - $testParams.passAnonymousToken = "false" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.passAnonymousToken -eq $testParams.passAnonymousToken | Should be $true - } - - It 'Passes Pass Anon Token Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - passAnonymousToken = "true" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.passAnonymousToken -eq "false") - { - $testParams.passAnonymousToken = "false" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Pass Anon Token Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - passAnonymousToken = "true" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.passAnonymousToken -eq "true") - { - $testParams.passAnonymousToken = "false" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Logon Type' { - $testParams =@{ - Name = $apName - Ensure = "Present" - logonType = "LogonService" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.logonType -eq "LogonService") - { - $testParams.logonType = "LogonBatch" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.logonType -eq $testParams.logonType | Should be $true - } - - It 'Passes Logon Type Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - logonType = "LogonService" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.logonType -eq "LogonBatch") - { - $testParams.logonType = "LogonBatch" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Logon Type Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - logonType = "LogonService" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.logonType -eq "LogonService") - { - $testParams.logonType = "LogonBatch" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Manual Group Membership' { - $testParams =@{ - Name = $apName - Ensure = "Present" - manualGroupMembership = "true" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.manualGroupMembership -eq "true") - { - $testParams.manualGroupMembership = "false" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.manualGroupMembership -eq $testParams.manualGroupMembership | Should be $true - } - - It 'Passes Manual Group Membership Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - manualGroupMembership = "true" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.manualGroupMembership -eq "false") - { - $testParams.manualGroupMembership = "false" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Manual Group Membership Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - manualGroupMembership = "true" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.manualGroupMembership -eq "true") - { - $testParams.manualGroupMembership = "false" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Idle Timeout' { - $testParams =@{ - Name = $apName - Ensure = "Present" - idleTimeout = "00:25:00" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.idleTimeout -eq "00:25:00") - { - $testParams.idleTimeout = "00:20:00" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.idleTimeout -eq $testParams.idleTimeout | Should be $true - } - - It 'Passes Idle Timeout Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - idleTimeout = "00:25:00" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.idleTimeout -eq "00:20:00") - { - $testParams.idleTimeout = "00:20:00" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Idle Timeout Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - idleTimeout = "00:25:00" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.idleTimeout -eq "00:25:00") - { - $testParams.idleTimeout = "00:20:00" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Max Processes' { - $testParams =@{ - Name = $apName - Ensure = "Present" - maxProcesses = "2" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.maxProcesses -eq "2") - { - $testParams.maxProcesses = "1" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.maxProcesses -eq $testParams.maxProcesses | Should be $true - } - - It 'Passes Max Processes Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - maxProcesses = "2" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.maxProcesses -eq "1") - { - $testParams.maxProcesses = "1" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Max Processes Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - maxProcesses = "2" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.maxProcesses -eq "2") - { - $testParams.maxProcesses = "1" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Shutdown Time Limit' { - $testParams =@{ - Name = $apName - Ensure = "Present" - shutdownTimeLimit = "00:02:30" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.shutdownTimeLimit -eq "00:02:30") - { - $testParams.shutdownTimeLimit = "00:01:30" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.shutdownTimeLimit -eq $testParams.shutdownTimeLimit | Should be $true - } - - It 'Passes Shutdown Time Limit Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - shutdownTimeLimit = "00:02:30" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.shutdownTimeLimit -eq "00:01:30") - { - $testParams.shutdownTimeLimit = "00:01:30" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Shutdown Time Limit Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - shutdownTimeLimit = "00:02:30" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.shutdownTimeLimit -eq "00:02:30") - { - $testParams.shutdownTimeLimit = "00:01:30" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Startup Time Limit' { - $testParams =@{ - Name = $apName - Ensure = "Present" - startupTimeLimit = "00:02:30" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.startupTimeLimit -eq "00:02:30") - { - $testParams.startupTimeLimit = "00:01:30" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.startupTimeLimit -eq $testParams.startupTimeLimit | Should be $true - } - - It 'Passes Startup Time Limit Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - startupTimeLimit = "00:02:30" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.startupTimeLimit -eq "00:01:30") - { - $testParams.startupTimeLimit = "00:01:30" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Startup Time Limit Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - startupTimeLimit = "00:02:30" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.startupTimeLimit -eq "00:02:30") - { - $testParams.startupTimeLimit = "00:01:30" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Ping Interval' { - $testParams =@{ - Name = $apName - Ensure = "Present" - pingInterval = "00:02:30" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingInterval -eq "00:02:30") - { - $testParams.pingInterval = "00:01:30" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingInterval -eq $testParams.pingInterval | Should be $true - } - - It 'Passes Ping Interval Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - pingInterval = "00:02:30" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingInterval -eq "00:01:30") - { - $testParams.pingInterval = "00:01:30" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Ping Interval Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - pingInterval = "00:02:30" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingInterval -eq "00:02:30") - { - $testParams.pingInterval = "00:01:30" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Ping Response Time' { - $testParams =@{ - Name = $apName - Ensure = "Present" - pingResponseTime = "00:02:30" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingResponseTime -eq "00:02:30") - { - $testParams.pingResponseTime = "00:01:30" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingResponseTime -eq $testParams.pingResponseTime | Should be $true - } - - It 'Passes Ping Response Time Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - pingResponseTime = "00:02:30" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingResponseTime -eq "00:01:30") - { - $testParams.pingResponseTime = "00:01:30" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Ping Response Time Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - pingResponseTime = "00:02:30" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingResponseTime -eq "00:02:30") - { - $testParams.pingResponseTime = "00:01:30" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Ping Enabled' { - $testParams =@{ - Name = $apName - Ensure = "Present" - pingingEnabled = "false" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingingEnabled -eq "false") - { - $testParams.pingingEnabled = "true" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingingEnabled -eq $testParams.pingingEnabled | Should be $true - } - - It 'Passes Ping Enabled Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - pingingEnabled = "false" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingingEnabled -eq "true") - { - $testParams.pingingEnabled = "true" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Ping Enabled Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - pingingEnabled = "false" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.processModel.pingingEnabled -eq "false") - { - $testParams.pingingEnabled = "true" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Disallow Overlapping Rotation' { - $testParams =@{ - Name = $apName - Ensure = "Present" - disallowOverlappingRotation = "false" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.disallowOverlappingRotation -eq "false") - { - $testParams.disallowOverlappingRotation = "true" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.disallowOverlappingRotation -eq $testParams.disallowOverlappingRotation | Should be $true - } - - It 'Passes Disallow Overlapping Rotation Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - disallowOverlappingRotation = "false" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.disallowOverlappingRotation -eq "true") - { - $testParams.disallowOverlappingRotation = "true" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Disallow Overlapping Rotation Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - disallowOverlappingRotation = "false" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.disallowOverlappingRotation -eq "false") - { - $testParams.disallowOverlappingRotation = "true" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Disallow Rotation On Config Change' { - $testParams =@{ - Name = $apName - Ensure = "Present" - disallowRotationOnConfigChange = "false" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.disallowRotationOnConfigChange -eq "false") - { - $testParams.disallowRotationOnConfigChange = "true" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.disallowRotationOnConfigChange -eq $testParams.disallowRotationOnConfigChange | Should be $true - } - - It 'Passes Disallow Rotation On Config Change Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - disallowRotationOnConfigChange = "false" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.disallowRotationOnConfigChange -eq "true") - { - $testParams.disallowRotationOnConfigChange = "true" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Disallow Rotation On Config Change Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - disallowRotationOnConfigChange = "false" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.disallowRotationOnConfigChange -eq "false") - { - $testParams.disallowRotationOnConfigChange = "true" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Log Event On Recycle' { - $testParams =@{ - Name = $apName - Ensure = "Present" - logEventOnRecycle = "Time, Memory" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.logEventOnRecycle -eq "Time, Memory") - { - $testParams.logEventOnRecycle = "Time, Memory, PrivateMemory" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.logEventOnRecycle -eq $testParams.logEventOnRecycle | Should be $true - } - - It 'Passes Log Event On Recycle Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - logEventOnRecycle = "Time, Memory" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.logEventOnRecycle -eq "Time, Memory, PrivateMemory") - { - $testParams.logEventOnRecycle = "Time, Memory, PrivateMemory" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Log Event On Recycle Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - logEventOnRecycle = "Time, Memory" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.logEventOnRecycle -eq "Time, Memory") - { - $testParams.logEventOnRecycle = "Time, Memory, PrivateMemory" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Restart Mem Limit' { - $testParams =@{ - Name = $apName - Ensure = "Present" - restartMemoryLimit = "1" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.memory -eq "1") - { - $testParams.restartMemoryLimit = "0" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.memory -eq $testParams.restartMemoryLimit | Should be $true - } - - It 'Passes Restart Mem Limit Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - restartMemoryLimit = "1" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.memory -eq "0") - { - $testParams.restartMemoryLimit = "0" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Restart Mem Limit Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - restartMemoryLimit = "1" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.memory -eq "1") - { - $testParams.restartMemoryLimit = "0" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Restart Private Mem Limit' { - $testParams =@{ - Name = $apName - Ensure = "Present" - restartPrivateMemoryLimit = "1" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.privateMemory -eq "1") - { - $testParams.restartPrivateMemoryLimit = "0" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.privateMemory -eq $testParams.restartPrivateMemoryLimit | Should be $true - } - - It 'Passes Restart Private Mem Limit Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - restartPrivateMemoryLimit = "1" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.privateMemory -eq "0") - { - $testParams.restartPrivateMemoryLimit = "0" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Restart Private Mem Limit Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - restartPrivateMemoryLimit = "1" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.privateMemory -eq "1") - { - $testParams.restartPrivateMemoryLimit = "0" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Restart Requests Limit' { - $testParams =@{ - Name = $apName - Ensure = "Present" - restartRequestsLimit = "1" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.requests -eq "1") - { - $testParams.restartRequestsLimit = "0" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.requests -eq $testParams.restartRequestsLimit | Should be $true - } - - It 'Passes Restart Requests Limit Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - restartRequestsLimit = "1" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.requests -eq "0") - { - $testParams.restartRequestsLimit = "0" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Restart Requests Limit Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - restartRequestsLimit = "1" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.requests -eq "1") - { - $testParams.restartRequestsLimit = "0" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Restart Time Limit' { - $testParams =@{ - Name = $apName - Ensure = "Present" - restartTimeLimit = "2.05:00:00" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.time -eq "2.05:00:00") - { - $testParams.restartTimeLimit = "1.05:00:00" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.time -eq $testParams.restartTimeLimit | Should be $true - } - - It 'Passes Restart Time Limit Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - restartTimeLimit = "2.05:00:00" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.time -eq "1.05:00:00") - { - $testParams.restartTimeLimit = "1.05:00:00" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Restart Time Limit Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - restartTimeLimit = "2.05:00:00" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.time -eq "2.05:00:00") - { - $testParams.restartTimeLimit = "1.05:00:00" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Restart Schedule' { - $testParams =@{ - Name = $apName - Ensure = "Present" - restartSchedule = "18:30:00" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.schedule.add.value -eq "18:30:00") - { - $testParams.restartSchedule = "10:30:00" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.schedule.add.value -eq $testParams.restartSchedule | Should be $true - } - - It 'Passes Restart Schedule Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - restartSchedule = "18:30:00" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.schedule.add.value -eq "10:30:00") - { - $testParams.restartSchedule = "10:30:00" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Restart Schedule Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - restartSchedule = "18:30:00" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.recycling.periodicRestart.schedule.add.value -eq "18:30:00") - { - $testParams.restartSchedule = "10:30:00" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Load Balancer Capabilities' { - $testParams =@{ - Name = $apName - Ensure = "Present" - loadBalancerCapabilities = "TcpLevel" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.loadBalancerCapabilities -eq "TcpLevel") - { - $testParams.loadBalancerCapabilities = "HttpLevel" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.loadBalancerCapabilities -eq $testParams.loadBalancerCapabilities | Should be $true - } - - It 'Passes Load Balancer Capabilities Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - loadBalancerCapabilities = "TcpLevel" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.loadBalancerCapabilities -eq "HttpLevel") - { - $testParams.loadBalancerCapabilities = "HttpLevel" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Load Balancer Capabilities Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - loadBalancerCapabilities = "TcpLevel" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.loadBalancerCapabilities -eq "TcpLevel") - { - $testParams.loadBalancerCapabilities = "HttpLevel" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Orphan Worker Process' { - $testParams =@{ - Name = $apName - Ensure = "Present" - orphanWorkerProcess = "true" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanWorkerProcess -eq "true") - { - $testParams.orphanWorkerProcess = "false" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanWorkerProcess -eq $testParams.orphanWorkerProcess | Should be $true - } - - It 'Passes Orphan Worker Process Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - orphanWorkerProcess = "true" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanWorkerProcess -eq "false") - { - $testParams.orphanWorkerProcess = "false" - } - - Test-TargetResource @testParams | Should be $true - } - - It 'Fails Orphan Worker Process Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - orphanWorkerProcess = "true" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanWorkerProcess -eq "true") - { - $testParams.orphanWorkerProcess = "false" - } - - Test-TargetResource @testParams | Should be $false - } - - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Orphan Action Exe' { - $testParams =@{ - Name = $apName - Ensure = "Present" - orphanActionExe = "test.exe" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanActionExe -eq "test.exe") - { - $testParams.orphanActionExe = "test1.exe" - } - - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanActionExe -eq $testParams.orphanActionExe | Should be $true - } - - It 'Passes Orphan Action Exe Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - orphanActionExe = "test.exe" - } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanActionExe -eq "test1.exe") - { - $testParams.orphanActionExe = "test1.exe" - } - Test-TargetResource @testParams | Should be $true - } + Function TestTargetResourceSame + { + <# - It 'Fails Orphan Action Exe Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - orphanActionExe = "test.exe" - } + .SYNOPSIS + Runs Test-TargetResource on $option so that when $option has the same value as the current setting, $true is returned. - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanActionExe -eq "test.exe") - { - $testParams.orphanActionExe = "test1.exe" - } + .DESCRIPTION + Runs Test-TargetResource on $option so that when $option has the same value as the current setting, $true is returned. - Test-TargetResource @testParams | Should be $false - } + .PARAMETER option + should be the name of the option as defined in xWebAppPool.psm1 - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Orphan Action Params' { - $testParams =@{ - Name = $apName - Ensure = "Present" - orphanActionParams = "test.exe" - } + .PARAMETER appcmdVal + The location that would be used to get this value via appcmd. - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanActionParams -eq "test.exe") - { - $testParams.orphanActionParams = "test1.exe" - } + .EXAMPLE + TestTargetResourceSame "autoStart" "add.autoStart" - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanActionParams -eq $testParams.orphanActionParams | Should be $true + #> + [OutputType([bool])] + Param($option,$appcmdVal) + $testParams =@{ + Name = "PesterAppPool" + Ensure = "Present" } + $curVal = Invoke-Expression "(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool 'PesterAppPool' /config:*)).$($appcmdVal))" + #Write-Host $curVal + $testParams.Add($option,$curVal) - It 'Passes Orphan Action Params Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - orphanActionParams = "test.exe" - } + #need to explicitly set it to the current value. This "resets" all the values so the previous tests don't interfere with this one + Set-TargetResource @testParams | Out-Null #So we only return the value of Test-TargetResource below - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanActionParams -eq "test1.exe") - { - $testParams.orphanActionParams = "test1.exe" - } + Test-TargetResource @testParams + Return + } - Test-TargetResource @testParams | Should be $true - } + Function TestTargetResourceDiff + { + <# - It 'Fails Orphan Action Params Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - orphanActionParams = "test.exe" - } + .SYNOPSIS + Runs Test-TargetResource on $option so that when $option has a different value as the current setting, $false is returned. - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.orphanActionParams -eq "test.exe") - { - $testParams.orphanActionParams = "test1.exe" - } + .DESCRIPTION + Runs Test-TargetResource on $option so that when $option has a different value as the current setting, $false is returned. - Test-TargetResource @testParams | Should be $false - } + .PARAMETER option + should be the name of the option as defined in xWebAppPool.psm1 - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests + .PARAMETER appcmdVal + The location that would be used to get this value via appcmd. - It 'Should set Rapid Fail Protection' { - $testParams =@{ - Name = $apName - Ensure = "Present" - rapidFailProtection = "true" - } + .PARAMETER value1 + A valid value that $option can be set to. Must be different than value2 - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtection -eq "true") - { - $testParams.rapidFailProtection = "false" - } + .PARAMETER value2 + A valid value that $option can be set to. Must be different than value1 - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtection -eq $testParams.rapidFailProtection | Should be $true + .EXAMPLE + TestTargetResourceDiff "autoStart" "add.autoStart" "true" "false" + + #> + [OutputType([bool])] + Param($option,$appcmdVal,$value1,$value2) + $testParams =@{ + Name = "PesterAppPool" + Ensure = "Present" } + + $testParams.Add($option,$value1) + Set-TargetResource @testParams | Out-Null #So we only return the value of Test-TargetResource below + $testParams.$option = $value2 + Test-TargetResource @testParams + Return + } - It 'Passes Rapid Fail Protection Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - rapidFailProtection = "true" - } + Function SetTargetResource + { + <# - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtection -eq "false") - { - $testParams.rapidFailProtection = "false" - } + .SYNOPSIS + Runs Set-TargetResource on $option and then verifies that option was changed to the desired value. Returns $true if option was changed. + + .DESCRIPTION + Runs Set-TargetResource on $option and then verifies that option was changed to the desired value. Returns $true if option was changed. + + .PARAMETER option + should be the name of the option as defined in xWebAppPool.psm1 + + .PARAMETER appcmdVal + The location that would be used to get this value via appcmd. + + .PARAMETER value1 + A valid value that $option can be set to. Must be different than value2 + + .PARAMETER value2 + A valid value that $option can be set to. Must be different than value1 - Test-TargetResource @testParams | Should be $true + .EXAMPLE + SetTargetResource "autoStart" "add.autoStart" "true" "false" + + #> + [OutputType([bool])] + Param($option,$appcmdVal,$value1,$value2) + $testParams =@{ + Name = "PesterAppPool" + Ensure = "Present" + } + $curVal = Invoke-Expression "(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool 'PesterAppPool' /config:*)).$($appcmdVal))" + if($curVal -ne $value1) + { + $testParams.Add($option,$value1) + Set-TargetResource @testParams | Out-Null #So we only return the value of Test-TargetResource below + $curVal = Invoke-Expression "(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool 'PesterAppPool' /config:*)).$($appcmdVal))" + $value1 -eq $curVal + } + else + { + $testParams.Add($option,$value2) + Set-TargetResource @testParams | Out-Null #So we only return the value of Test-TargetResource below + $curVal = Invoke-Expression "(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool 'PesterAppPool' /config:*)).$($appcmdVal))" + $value2 -eq $curVal } - It 'Fails Rapid Fail Protection Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - rapidFailProtection = "true" - } + Return + } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtection -eq "true") - { - $testParams.rapidFailProtection = "false" - } + try + { + $baseParams =@{ + Name = "PesterAppPool" + Ensure = "Present" + } - Test-TargetResource @testParams | Should be $false + It 'Should pass Test-xDscResource Schema Validation' { + $result = Test-xDscResource MSFT_xWebAppPool + $result | Should Be $true } - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Rapid Fail Protection Interval' { + It 'Should create a new App Pool' { $testParams =@{ - Name = $apName + Name = "PesterAppPool" Ensure = "Present" - rapidFailProtectionInterval = "00:15:00" } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtectionInterval -eq "00:15:00") + # if the app pool exists, remove it + if((Get-ChildItem IIS:\apppools).Name.Contains("PesterAppPool")) { - $testParams.rapidFailProtectionInterval = "00:05:00" + Remove-WebAppPool -Name "PesterAppPool" -ErrorAction Stop } Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtectionInterval -eq $testParams.rapidFailProtectionInterval | Should be $true + (Get-ChildItem IIS:\apppools).Name.Contains("PesterAppPool") | Should be $true } + + Context 'Test-TargetResource' { + It 'Passes test when App Pool does exist'{ + $testParams =@{ + Name = "PesterAppPool" + Ensure = "Present" + } - It 'Passes Rapid Fail Protection Interval Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - rapidFailProtectionInterval = "00:15:00" + Test-TargetResource @testParams | Should be $true + } + + It 'Passes autoStart Test when same' { + + TestTargetResourceSame "autoStart" "add.autoStart" | Should be $true } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtectionInterval -eq "00:05:00") - { - $testParams.rapidFailProtectionInterval = "00:05:00" + It 'Fails autoStart Test when different' { + + TestTargetResourceDiff "autoStart" "add.autoStart" "true" "false"| Should be $false } - Test-TargetResource @testParams | Should be $true - } + It 'Passes Runtime Version Test when same' { + + TestTargetResourceSame "managedRuntimeVersion" "add.managedRuntimeVersion" | Should be $true + } - It 'Fails Rapid Fail Protection Interval Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - rapidFailProtectionInterval = "00:15:00" + It 'Fails Runtime Version Test when different' { + + TestTargetResourceDiff "managedRuntimeVersion" "add.managedRuntimeVersion" "v4.0" "v2.0" | Should be $false } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtectionInterval -eq "00:15:00") - { - $testParams.rapidFailProtectionInterval = "00:05:00" + It 'Passes Managed Pipeline Mode Test when same' { + + TestTargetResourceSame "managedPipelineMode" "add.managedPipelineMode" | Should be $true } - Test-TargetResource @testParams | Should be $false - } + It 'Fails Managed Pipeline Mode Test when different' { + + TestTargetResourceDiff "managedPipelineMode" "add.managedPipelineMode" "Integrated" "Classic"| Should be $false + } - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Rapid Fail Protection Max Crashes' { - $testParams =@{ - Name = $apName - Ensure = "Present" - rapidFailProtectionMaxCrashes = "15" + It 'Passes Start Mode Test when same' { + + TestTargetResourceSame "startMode" "add.startMode" | Should be $true } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtectionMaxCrashes -eq "15") - { - $testParams.rapidFailProtectionMaxCrashes = "05" + It 'Fails Start Mode Test when different' { + + TestTargetResourceDiff "startMode" "add.startMode" "AlwaysRunning" "OnDemand" | Should be $false } - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtectionMaxCrashes -eq $testParams.rapidFailProtectionMaxCrashes | Should be $true - } + It 'Passes Identity Type Test when same' { + + TestTargetResourceSame "identityType" "add.processModel.identityType" | Should be $true + } - It 'Passes Rapid Fail Protection Interval Max Crashes when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - rapidFailProtectionMaxCrashes = "15" + It 'Fails Identity Type Test when different' { + + TestTargetResourceDiff "identityType" "add.processModel.identityType" "ApplicationPoolIdentity" "LocalSystem" | Should be $false } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtectionMaxCrashes -eq "05") - { - $testParams.rapidFailProtectionMaxCrashes = "05" + It 'Passes Load User Profile Test when same' { + + TestTargetResourceSame "loadUserProfile" "add.processModel.loadUserProfile" | Should be $true } - Test-TargetResource @testParams | Should be $true - } + It 'Fails Load User Profile Test when different' { + + TestTargetResourceDiff "loadUserProfile" "add.processModel.loadUserProfile" "true" "false" | Should be $false + } - It 'Fails Rapid Fail Protection Max Crashes Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - rapidFailProtectionMaxCrashes = "15" + It 'Passes Queue Length Test when same' { + + TestTargetResourceSame "queueLength" "add.queueLength" | Should be $true } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.rapidFailProtectionMaxCrashes -eq "15") - { - $testParams.rapidFailProtectionMaxCrashes = "05" + It 'Fails Queue Length Test when different' { + + TestTargetResourceDiff "queueLength" "add.queueLength" "2000" "1000" | Should be $false } - Test-TargetResource @testParams | Should be $false - } + It 'Passes Enable 32bit Test when same' { + + TestTargetResourceSame "enable32BitAppOnWin64" "add.enable32BitAppOnWin64" | Should be $true + } - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Auto Shutdown Exe' { - $testParams =@{ - Name = $apName - Ensure = "Present" - autoShutdownExe = "test.exe" + It 'Fails Enable 32bit Test when different' { + + TestTargetResourceDiff "enable32BitAppOnWin64" "add.enable32BitAppOnWin64" "true" "false" | Should be $false } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.autoShutdownExe -eq "test.exe") - { - $testParams.autoShutdownExe = "test1.exe" + It 'Passes Config Override Test when same' { + + TestTargetResourceSame "enableConfigurationOverride" "add.enableConfigurationOverride" | Should be $true } - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.autoShutdownExe -eq $testParams.autoShutdownExe | Should be $true - } + It 'Fails Config Override Test when different' { + + TestTargetResourceDiff "enableConfigurationOverride" "add.enableConfigurationOverride" "true" "false" | Should be $false + } - It 'Passes Auto Shutdown Exe Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - autoShutdownExe = "test.exe" + It 'Passes Pass Anon Token Test when same' { + + TestTargetResourceSame "passAnonymousToken" "add.passAnonymousToken" | Should be $true } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.autoShutdownExe -eq "test1.exe") - { - $testParams.autoShutdownExe = "test1.exe" + It 'Fails Pass Anon Token Test when different' { + + TestTargetResourceDiff "passAnonymousToken" "add.passAnonymousToken" "true" "false" | Should be $false } - Test-TargetResource @testParams | Should be $true - } + It 'Passes Logon Type Test when same' { + + TestTargetResourceSame "logonType" "add.processModel.logonType" | Should be $true + } - It 'Fails Auto Shutdown Exe Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - autoShutdownExe = "test.exe" + It 'Fails Logon Type Test when different' { + + TestTargetResourceDiff "logonType" "add.processModel.logonType" "LogonService" "LogonBatch" | Should be $false } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.autoShutdownExe -eq "test.exe") - { - $testParams.autoShutdownExe = "test1.exe" + It 'Passes Manual Group Membership Test when same' { + + TestTargetResourceSame "manualGroupMembership" "add.processModel.manualGroupMembership" | Should be $true } - Test-TargetResource @testParams | Should be $false - } + It 'Fails Manual Group Membership Test when different' { + + TestTargetResourceDiff "manualGroupMembership" "add.processModel.manualGroupMembership" "true" "false" | Should be $false + } - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set Auto Shutdown Params' { - $testParams =@{ - Name = $apName - Ensure = "Present" - autoShutdownParams = "test.exe" + It 'Passes Idle Timeout Test when same' { + + TestTargetResourceSame "idleTimeout" "add.processModel.idleTimeout" | Should be $true } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.autoShutdownParams -eq "test.exe") - { - $testParams.autoShutdownParams = "test1.exe" + It 'Fails Idle Timeout Test when different' { + + TestTargetResourceDiff "idleTimeout" "add.processModel.idleTimeout" "00:25:00" "00:20:00" | Should be $false } - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.autoShutdownParams -eq $testParams.autoShutdownParams | Should be $true - } + It 'Passes Max Processes Test when same' { + + TestTargetResourceSame "maxProcesses" "add.processModel.maxProcesses" | Should be $true + } - It 'Passes Auto Shutdown Params Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - autoShutdownParams = "test.exe" + It 'Fails Max Processes Test when different' { + + TestTargetResourceDiff "maxProcesses" "add.processModel.maxProcesses" "2" "1" | Should be $false } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.autoShutdownParams -eq "test1.exe") - { - $testParams.autoShutdownParams = "test1.exe" + It 'Passes Shutdown Time Limit Test when same' { + + TestTargetResourceSame "shutdownTimeLimit" "add.processModel.shutdownTimeLimit" | Should be $true } - Test-TargetResource @testParams | Should be $true - } + It 'Fails Shutdown Time Limit Test when different' { + + TestTargetResourceDiff "shutdownTimeLimit" "add.processModel.shutdownTimeLimit" "00:02:30" "00:01:30" | Should be $false + } - It 'Fails Auto Shutdown Params Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - autoShutdownParams = "test.exe" + It 'Passes Startup Time Limit Test when same' { + + TestTargetResourceSame "startupTimeLimit" "add.processModel.startupTimeLimit" | Should be $true } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.failure.autoShutdownParams -eq "test.exe") - { - $testParams.autoShutdownParams = "test1.exe" + It 'Fails Startup Time Limit Test when different' { + + TestTargetResourceDiff "startupTimeLimit" "add.processModel.startupTimeLimit" "00:02:30" "00:01:30" | Should be $false } - Test-TargetResource @testParams | Should be $false - } + It 'Passes Ping Interval Test when same' { + + TestTargetResourceSame "pingInterval" "add.processModel.pingInterval" | Should be $true + } - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set CPU Limit' { - $testParams =@{ - Name = $apName - Ensure = "Present" - cpuLimit = "1" + It 'Fails Ping Interval Test when different' { + + TestTargetResourceDiff "pingInterval" "add.processModel.pingInterval" "00:02:30" "00:01:30" | Should be $false } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.limit -eq "1") - { - $testParams.cpuLimit = "0" + It 'Passes Ping Response Test when same' { + + TestTargetResourceSame "pingResponseTime" "add.processModel.pingResponseTime" | Should be $true } - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.limit -eq $testParams.cpuLimit | Should be $true - } + It 'Fails Ping Response Test when different' { + + TestTargetResourceDiff "pingResponseTime" "add.processModel.pingResponseTime" "00:02:30" "00:01:30" | Should be $false + } - It 'Passes CPU Limit Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - cpuLimit = "1" + It 'Passes Ping Enabled Test when same' { + + TestTargetResourceSame "pingingEnabled" "add.processModel.pingingEnabled" | Should be $true } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.limit -eq "0") - { - $testParams.cpuLimit = "0" + It 'Fails Ping Enabled Test when different' { + + TestTargetResourceDiff "pingingEnabled" "add.processModel.pingingEnabled" "true" "false" | Should be $false } - Test-TargetResource @testParams | Should be $true - } + It 'Passes Disallow Overlapping Rotation Test when same' { + + TestTargetResourceSame "disallowOverlappingRotation" "add.recycling.disallowOverlappingRotation" | Should be $true + } - It 'Fails CPU Limit Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - cpuLimit = "1" + It 'Fails Disallow Overlapping Rotation Test when different' { + + TestTargetResourceDiff "disallowOverlappingRotation" "add.recycling.disallowOverlappingRotation" "true" "false" | Should be $false } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.limit -eq "1") - { - $testParams.cpuLimit = "0" + It 'Passes Disallow Rotation On Config Change Test when same' { + + TestTargetResourceSame "disallowRotationOnConfigChange" "add.recycling.disallowRotationOnConfigChange" | Should be $true } - Test-TargetResource @testParams | Should be $false - } + It 'Fails Disallow Rotation On Config Change Test when different' { + + TestTargetResourceDiff "disallowRotationOnConfigChange" "add.recycling.disallowRotationOnConfigChange" "true" "false" | Should be $false + } - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set CPU Action' { - $testParams =@{ - Name = $apName - Ensure = "Present" - cpuAction = "Throttle" + It 'Passes Log Event On Recycle Test when same' { + + TestTargetResourceSame "logEventOnRecycle" "add.recycling.logEventOnRecycle" | Should be $true } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.action -eq "Throttle") - { - $testParams.cpuAction = "NoAction" + It 'Fails Log Event On Recycle Test when different' { + + TestTargetResourceDiff "logEventOnRecycle" "add.recycling.logEventOnRecycle" "Time, Memory" "Time, Memory, PrivateMemory" | Should be $false } - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.action -eq $testParams.cpuAction | Should be $true - } + It 'Passes Restart Mem Limit Test when same' { + + TestTargetResourceSame "restartMemoryLimit" "add.recycling.periodicRestart.memory" | Should be $true + } - It 'Passes CPU Action Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - cpuAction = "Throttle" + It 'Fails Restart Mem Limit Test when different' { + + TestTargetResourceDiff "restartMemoryLimit" "add.recycling.periodicRestart.memory" "0" "1" | Should be $false } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.action -eq "NoAction") - { - $testParams.cpuAction = "NoAction" + It 'Passes Restart Private Mem Limit Test when same' { + + TestTargetResourceSame "restartPrivateMemoryLimit" "add.recycling.periodicRestart.privateMemory" | Should be $true } - Test-TargetResource @testParams | Should be $true - } + It 'Fails Restart Private Mem Limit Test when different' { + + TestTargetResourceDiff "restartPrivateMemoryLimit" "add.recycling.periodicRestart.privateMemory" "0" "1" | Should be $false + } - It 'Fails CPU Action Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - cpuAction = "Throttle" + It 'Passes Restart Requests Limit Test when same' { + + TestTargetResourceSame "restartRequestsLimit" "add.recycling.periodicRestart.requests" | Should be $true } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.action -eq "Throttle") - { - $testParams.cpuAction = "NoAction" + It 'Fails Restart Requests Limit Test when different' { + + TestTargetResourceDiff "restartRequestsLimit" "add.recycling.periodicRestart.requests" "0" "1" | Should be $false } - Test-TargetResource @testParams | Should be $false - } + It 'Passes Restart Time Limit Test when same' { + + TestTargetResourceSame "restartTimeLimit" "add.recycling.periodicRestart.time" | Should be $true + } - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set CPU Reset Interval' { - $testParams =@{ - Name = $apName - Ensure = "Present" - cpuResetInterval = "00:15:00" + It 'Fails Restart Time Limit Test when different' { + + TestTargetResourceDiff "restartTimeLimit" "add.recycling.periodicRestart.time" "2.05:00:00" "1.05:00:00" | Should be $false } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.resetInterval -eq "00:15:00") - { - $testParams.cpuResetInterval = "00:05:00" + It 'Passes Restart Schedule Test when same' { + + TestTargetResourceSame "restartSchedule" "add.recycling.periodicRestart.schedule.add.value" | Should be $true } - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.resetInterval -eq $testParams.cpuResetInterval | Should be $true - } + It 'Fails Restart Schedule Test when different' { + + TestTargetResourceDiff "restartSchedule" "add.recycling.periodicRestart.schedule.add.value" "18:30:00" "10:30:00" | Should be $false + } - It 'Passes CPU Reset Interval Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - cpuResetInterval = "00:15:00" + It 'Passes Load Balancer Capabilities Test when same' { + + TestTargetResourceSame "loadBalancerCapabilities" "add.failure.loadBalancerCapabilities" | Should be $true } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.resetInterval -eq "00:05:00") - { - $testParams.cpuResetInterval = "00:05:00" + It 'Fails Load Balancer Capabilities Test when different' { + + TestTargetResourceDiff "loadBalancerCapabilities" "add.failure.loadBalancerCapabilities" "HttpLevel" "TcpLevel" | Should be $false } - Test-TargetResource @testParams | Should be $true - } + It 'Passes Orphan Worker Process Test when same' { + + TestTargetResourceSame "orphanWorkerProcess" "add.failure.orphanWorkerProcess" | Should be $true + } - It 'Fails CPU Reset Interval Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - cpuResetInterval = "00:15:00" + It 'Fails Orphan Worker Process Test when different' { + + TestTargetResourceDiff "orphanWorkerProcess" "add.failure.orphanWorkerProcess" "true" "false" | Should be $false } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.resetInterval -eq "00:15:00") - { - $testParams.cpuResetInterval = "00:05:00" + It 'Passes Orphan Action Exe Test when same' { + + TestTargetResourceSame "orphanActionExe" "add.failure.orphanActionExe" | Should be $true } - Test-TargetResource @testParams | Should be $false - } + It 'Fails Orphan Action Exe Test when different' { + + TestTargetResourceDiff "orphanActionExe" "add.failure.orphanActionExe" "test.exe" "test1.exe" | Should be $false + } - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set CPU Smp Affinitized' { - $testParams =@{ - Name = $apName - Ensure = "Present" - cpuSmpAffinitized = "true" + It 'Passes Orphan Action Params Test when same' { + + TestTargetResourceSame "orphanActionParams" "add.failure.orphanActionParams" | Should be $true } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpAffinitized -eq "true") - { - $testParams.cpuSmpAffinitized = "false" + It 'Fails Orphan Action Params Test when different' { + + TestTargetResourceDiff "orphanActionParams" "add.failure.orphanActionParams" "test.exe" "test1.exe" | Should be $false } - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpAffinitized -eq $testParams.cpuSmpAffinitized | Should be $true - } + It 'Passes Rapid Fail Protection Test when same' { + + TestTargetResourceSame "rapidFailProtection" "add.failure.rapidFailProtection" | Should be $true + } - It 'Passes CPU Smp Affinitized Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - cpuSmpAffinitized = "true" + It 'Fails Rapid Fail Protection Test when different' { + + TestTargetResourceDiff "rapidFailProtection" "add.failure.rapidFailProtection" "true" "false" | Should be $false } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpAffinitized -eq "false") - { - $testParams.cpuSmpAffinitized = "false" + It 'Passes Rapid Fail Protection Interval Test when same' { + + TestTargetResourceSame "rapidFailProtectionInterval" "add.failure.rapidFailProtectionInterval" | Should be $true } - Test-TargetResource @testParams | Should be $true - } + It 'Fails Rapid Fail Protection Interval Test when different' { + + TestTargetResourceDiff "rapidFailProtectionInterval" "add.failure.rapidFailProtectionInterval" "00:15:00" "00:05:00" | Should be $false + } - It 'Fails CPU Smp Affinitized Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - cpuSmpAffinitized = "true" + It 'Passes Rapid Fail Protection Interval Max Crashes Test when same' { + + TestTargetResourceSame "rapidFailProtectionMaxCrashes" "add.failure.rapidFailProtectionMaxCrashes" | Should be $true } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpAffinitized -eq "true") - { - $testParams.cpuSmpAffinitized = "false" + It 'Fails Rapid Fail Protection Interval Max Crashes Test when different' { + + TestTargetResourceDiff "rapidFailProtectionMaxCrashes" "add.failure.rapidFailProtectionMaxCrashes" "15:00" "05" | Should be $false } - Test-TargetResource @testParams | Should be $false - } + It 'Passes Auto Shutdown Exe Test when same' { + + TestTargetResourceSame "autoShutdownExe" "add.failure.autoShutdownExe" | Should be $true + } - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set CPU Smp Processor Affinity Mask' { - $testParams =@{ - Name = $apName - Ensure = "Present" - cpuSmpProcessorAffinityMask = "4294967294" + It 'Fails Auto Shutdown Exe Test when different' { + + TestTargetResourceDiff "autoShutdownExe" "add.failure.autoShutdownExe" "test.exe" "test1.exe" | Should be $false } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpProcessorAffinityMask -eq "4294967294") - { - $testParams.cpuSmpProcessorAffinityMask = "4294967295" + It 'Passes Auto Shutdown Params Test when same' { + + TestTargetResourceSame "autoShutdownParams" "add.failure.autoShutdownParams" | Should be $true } - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpProcessorAffinityMask -eq $testParams.cpuSmpProcessorAffinityMask | Should be $true - } + It 'Fails Auto Shutdown Params Test when different' { + + TestTargetResourceDiff "autoShutdownParams" "add.failure.autoShutdownParams" "test.exe" "test1.exe" | Should be $false + } - It 'Passes CPU Smp Processor Affinity Mask Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - cpuSmpProcessorAffinityMask = "4294967294" + It 'Passes CPU Limit Test when same' { + + TestTargetResourceSame "cpuLimit" "add.cpu.limit" | Should be $true } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpProcessorAffinityMask -eq "4294967295") - { - $testParams.cpuSmpProcessorAffinityMask = "4294967295" + It 'Fails CPU Limit Test Test when different' { + + TestTargetResourceDiff "cpuLimit" "add.cpu.limit" "1" "0" | Should be $false } - Test-TargetResource @testParams | Should be $true - } + It 'Passes CPU Action Test when same' { + + TestTargetResourceSame "cpuAction" "add.cpu.action" | Should be $true + } - It 'Fails CPU Smp Processor Affinity Mask Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - cpuSmpProcessorAffinityMask = "4294967294" + It 'Fails CPU Action Test when different' { + + TestTargetResourceDiff "cpuAction" "add.cpu.action" "Throttle" "NoAction" | Should be $false } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpProcessorAffinityMask -eq "4294967294") - { - $testParams.cpuSmpProcessorAffinityMask = "4294967295" + It 'Passes CPU Reset Interval Test when same' { + + TestTargetResourceSame "cpuResetInterval" "add.cpu.resetInterval" | Should be $true } - Test-TargetResource @testParams | Should be $false - } + It 'Fails CPU Reset Interval Test when different' { + + TestTargetResourceDiff "cpuResetInterval" "add.cpu.resetInterval" "00:15:00" "00:05:00" | Should be $false + } - Set-TargetResource @baseParams #need to remove after each test set so previous tests don't affect the next tests - - It 'Should set CPU Smp Processor Affinity Mask 2' { - $testParams =@{ - Name = $apName - Ensure = "Present" - cpuSmpProcessorAffinityMask2 = "4294967294" + It 'Passes CPU Smp Affinitized Test when same' { + + TestTargetResourceSame "cpuSmpAffinitized" "add.cpu.smpAffinitized" | Should be $true } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpProcessorAffinityMask2 -eq "4294967294") - { - $testParams.cpuSmpProcessorAffinityMask2 = "4294967295" + It 'Fails CPU Smp Affinitized Test when different' { + + TestTargetResourceDiff "cpuSmpAffinitized" "add.cpu.smpAffinitized" "true" "false" | Should be $false } - Set-TargetResource @testParams - ([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpProcessorAffinityMask2 -eq $testParams.cpuSmpProcessorAffinityMask2 | Should be $true - } + It 'Passes CPU Smp Processor Affinity Mask Test when same' { + + TestTargetResourceSame "cpuSmpProcessorAffinityMask" "add.cpu.smpProcessorAffinityMask" | Should be $true + } - It 'Passes CPU Smp Processor Affinity Mask 2 Test when same' { - $testParams =@{ - Name = $apName - Ensure = "Present" - cpuSmpProcessorAffinityMask2 = "4294967294" + It 'Fails CPU Smp Processor Affinity Mask Test when different' { + + TestTargetResourceDiff "cpuSmpProcessorAffinityMask" "add.cpu.smpProcessorAffinityMask" "4294967294" "4294967295" | Should be $false } - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpProcessorAffinityMask2 -eq "4294967295") - { - $testParams.cpuSmpProcessorAffinityMask2 = "4294967295" + It 'Passes CPU Smp Processor Affinity Mask 2 Test when same' { + + TestTargetResourceSame "cpuSmpProcessorAffinityMask2" "add.cpu.smpProcessorAffinityMask2" | Should be $true } - Test-TargetResource @testParams | Should be $true + It 'Fails CPU Smp Processor Affinity Mask 2 Test when different' { + + TestTargetResourceDiff "cpuSmpProcessorAffinityMask2" "add.cpu.smpProcessorAffinityMask2" "4294967294" "4294967295" | Should be $false + } } - - It 'Fails CPU Smp Processor Affinity Mask 2 Test when different' { - $testParams =@{ - Name = $apName - Ensure = "Present" - cpuSmpProcessorAffinityMask2 = "4294967294" + + Context 'Set-TargetResource' { + It 'Should set autoStart Test ' { + + SetTargetResource "autoStart" "add.autoStart" "true" "false"| Should be $true } - - if(([xml](& $env:SystemRoot\system32\inetsrv\appcmd.exe list apppool $apName /config:*)).add.cpu.smpProcessorAffinityMask2 -eq "4294967294") - { - $testParams.cpuSmpProcessorAffinityMask2 = "4294967295" + + It 'Should set Runtime Version Test ' { + + SetTargetResource "managedRuntimeVersion" "add.managedRuntimeVersion" "v4.0" "v2.0" | Should be $true + } + + It 'Should set Managed Pipeline Mode Test ' { + + SetTargetResource "managedPipelineMode" "add.managedPipelineMode" "Integrated" "Classic"| Should be $true + } + + It 'Should set Start Mode Test ' { + + SetTargetResource "startMode" "add.startMode" "AlwaysRunning" "OnDemand" | Should be $true + } + + It 'Should set Identity Type Test ' { + + SetTargetResource "identityType" "add.processModel.identityType" "ApplicationPoolIdentity" "LocalSystem" | Should be $true + } + + It 'Should set Load User Profile Test ' { + + SetTargetResource "loadUserProfile" "add.processModel.loadUserProfile" "true" "false" | Should be $true + } + + It 'Should set Queue Length Test ' { + + SetTargetResource "queueLength" "add.queueLength" "2000" "1000" | Should be $true + } + + It 'Should set Enable 32bit Test ' { + + SetTargetResource "enable32BitAppOnWin64" "add.enable32BitAppOnWin64" "true" "false" | Should be $true + } + + It 'Should set Config Override Test ' { + + SetTargetResource "enableConfigurationOverride" "add.enableConfigurationOverride" "true" "false" | Should be $true + } + + It 'Should set Pass Anon Token Test ' { + + SetTargetResource "passAnonymousToken" "add.passAnonymousToken" "true" "false" | Should be $true + } + + It 'Should set Logon Type Test ' { + + SetTargetResource "logonType" "add.processModel.logonType" "LogonService" "LogonBatch" | Should be $true + } + + It 'Should set Manual Group Membership Test ' { + + SetTargetResource "manualGroupMembership" "add.processModel.manualGroupMembership" "true" "false" | Should be $true + } + + It 'Should set Idle Timeout Test ' { + + SetTargetResource "idleTimeout" "add.processModel.idleTimeout" "00:25:00" "00:20:00" | Should be $true + } + + It 'Should set Max Processes Test ' { + + SetTargetResource "maxProcesses" "add.processModel.maxProcesses" "2" "1" | Should be $true + } + + It 'Should set Shutdown Time Limit Test ' { + + SetTargetResource "shutdownTimeLimit" "add.processModel.shutdownTimeLimit" "00:02:30" "00:01:30" | Should be $true + } + + It 'Should set Startup Time Limit Test ' { + + SetTargetResource "startupTimeLimit" "add.processModel.startupTimeLimit" "00:02:30" "00:01:30" | Should be $true + } + + It 'Should set Ping Interval Test ' { + + SetTargetResource "pingInterval" "add.processModel.pingInterval" "00:02:30" "00:01:30" | Should be $true + } + + It 'Should set Ping Response Test ' { + + SetTargetResource "pingResponseTime" "add.processModel.pingResponseTime" "00:02:30" "00:01:30" | Should be $true + } + + It 'Should set Ping Enabled Test ' { + + SetTargetResource "pingingEnabled" "add.processModel.pingingEnabled" "true" "false" | Should be $true + } + + It 'Should set Disallow Overlapping Rotation Test ' { + + SetTargetResource "disallowOverlappingRotation" "add.recycling.disallowOverlappingRotation" "true" "false" | Should be $true + } + + It 'Should set Disallow Rotation On Config Change Test ' { + + SetTargetResource "disallowRotationOnConfigChange" "add.recycling.disallowRotationOnConfigChange" "true" "false" | Should be $true + } + + It 'Should set Log Event On Recycle Test ' { + + SetTargetResource "logEventOnRecycle" "add.recycling.logEventOnRecycle" "Time, Memory" "Time, Memory, PrivateMemory" | Should be $true + } + + It 'Should set Restart Mem Limit Test ' { + + SetTargetResource "restartMemoryLimit" "add.recycling.periodicRestart.memory" "0" "1" | Should be $true + } + + It 'Should set Restart Private Mem Limit Test ' { + + SetTargetResource "restartPrivateMemoryLimit" "add.recycling.periodicRestart.privateMemory" "0" "1" | Should be $true + } + + It 'Should set Restart Requests Limit Test ' { + + SetTargetResource "restartRequestsLimit" "add.recycling.periodicRestart.requests" "0" "1" | Should be $true + } + + It 'Should set Restart Time Limit Test ' { + + SetTargetResource "restartTimeLimit" "add.recycling.periodicRestart.time" "2.05:00:00" "1.05:00:00" | Should be $true + } + + It 'Should set Restart Schedule Test ' { + + SetTargetResource "restartSchedule" "add.recycling.periodicRestart.schedule.add.value" "18:30:00" "10:30:00" | Should be $true + } + + It 'Should set Load Balancer Capabilities Test ' { + + SetTargetResource "loadBalancerCapabilities" "add.failure.loadBalancerCapabilities" "HttpLevel" "TcpLevel" | Should be $true + } + + It 'Should set Orphan Worker Process Test ' { + + SetTargetResource "orphanWorkerProcess" "add.failure.orphanWorkerProcess" "true" "false" | Should be $true + } + + It 'Should set Orphan Action Exe Test ' { + + SetTargetResource "orphanActionExe" "add.failure.orphanActionExe" "test.exe" "test1.exe" | Should be $true + } + + It 'Should set Orphan Action Params Test ' { + + SetTargetResource "orphanActionParams" "add.failure.orphanActionParams" "test.exe" "test1.exe" | Should be $true + } + + It 'Should set Rapid Fail Protection Test ' { + + SetTargetResource "rapidFailProtection" "add.failure.rapidFailProtection" "true" "false" | Should be $true + } + + It 'Should set Rapid Fail Protection Interval Test ' { + + SetTargetResource "rapidFailProtectionInterval" "add.failure.rapidFailProtectionInterval" "00:15:00" "00:05:00" | Should be $true + } + + It 'Should set Rapid Fail Protection Interval Max Crashes Test ' { + + SetTargetResource "rapidFailProtectionMaxCrashes" "add.failure.rapidFailProtectionMaxCrashes" "15" "05" | Should be $true + } + + It 'Should set Auto Shutdown Exe Test ' { + + SetTargetResource "autoShutdownExe" "add.failure.autoShutdownExe" "test.exe" "test1.exe" | Should be $true + } + + It 'Should set Auto Shutdown Params Test ' { + + SetTargetResource "autoShutdownParams" "add.failure.autoShutdownParams" "test.exe" "test1.exe" | Should be $true + } + + It 'Should set CPU Limit Test Test ' { + + SetTargetResource "cpuLimit" "add.cpu.limit" "1" "0" | Should be $true + } + + It 'Should set CPU Action Test ' { + + SetTargetResource "cpuAction" "add.cpu.action" "Throttle" "NoAction" | Should be $true + } + + It 'Should set CPU Reset Interval Test ' { + + SetTargetResource "cpuResetInterval" "add.cpu.resetInterval" "00:15:00" "00:05:00" | Should be $true + } + + It 'Should set CPU Smp Affinitized Test ' { + + SetTargetResource "cpuSmpAffinitized" "add.cpu.smpAffinitized" "true" "false" | Should be $true + } + + It 'Should set CPU Smp Processor Affinity Mask Test ' { + + SetTargetResource "cpuSmpProcessorAffinityMask" "add.cpu.smpProcessorAffinityMask" "4294967294" "4294967295" | Should be $true + } + + It 'Should set CPU Smp Processor Affinity Mask 2 Test ' { + + SetTargetResource "cpuSmpProcessorAffinityMask2" "add.cpu.smpProcessorAffinityMask2" "4294967294" "4294967295" | Should be $true } - - Test-TargetResource @testParams | Should be $false } It 'Fails test when App Pool does not exist'{ $testParams =@{ - Name = $apName + Name = 'PesterAppPool' Ensure = "Present" } @@ -2091,9 +839,9 @@ Describe "MSFT_xWebAppPool"{ finally { # if the app pool exists, remove it - if((Get-ChildItem IIS:\apppools).Name.Contains($apName)) + if((Get-ChildItem IIS:\apppools).Name.Contains('PesterAppPool')) { - Remove-WebAppPool -Name $apName -ErrorAction Stop + Remove-WebAppPool -Name 'PesterAppPool' -ErrorAction Stop } } } From 3ca684240fa0acc50469bbcf7f2574ffc0a05291 Mon Sep 17 00:00:00 2001 From: Aaron Zuehlke Date: Thu, 19 Nov 2015 15:26:32 -0600 Subject: [PATCH 9/9] . --- .../MSFT_xIIsHandler/MSFT_xIisHandler.psm1 | 263 +++ .../MSFT_xIisHandler.schema.mof | 6 + .../MSFT_xIisFeatureDelegation.psm1 | 163 ++ .../MSFT_xIisFeatureDelegation.schema.mof | 6 + .../MSFT_xIisMimeTypeMapping.psm1 | 171 ++ .../MSFT_xIisMimeTypeMapping.schema.mof | 7 + .../MSFT_xIisModule/MSFT_xIisModule.psm1 | 46 +- .../MSFT_xWebAppPoolDefaults.psm1 | 160 ++ .../MSFT_xWebAppPoolDefaults.schema.mof | 8 + .../MSFT_xWebApplication.psm1 | 30 +- .../MSFT_xWebConfigKeyValue.psm1 | 32 +- .../MSFT_xWebSiteDefaults.psm1 | 188 +++ .../MSFT_xWebSiteDefaults.schema.mof | 10 + .../MSFT_xWebVirtualDirectory.psm1 | 64 +- DSCResources/MSFT_xWebsite/MSFT_xWebsite.psm1 | 792 ++++----- .../MSFT_xWebsite/MSFT_xWebsite.schema.mof | 11 +- ...Sample_xIisFeatureDelegation_AllowSome.ps1 | 39 + Examples/Sample_xIisHandler_Remove32Bit.ps1 | 52 + ...Sample_xIisMimeTypeMapping_RemoveVideo.ps1 | 55 + Examples/Sample_xIisServerDefaults.ps1 | 29 + .../Sample_xWebsite_ConfigurationData.psd1 | 18 +- Examples/Sample_xWebsite_NewWebsite.ps1 | 32 +- ...ebsite_NewWebsiteFromConfigurationData.ps1 | 32 +- Examples/Sample_xWebsite_RemoveDefault.ps1 | 16 +- Examples/Sample_xWebsite_WithSSLFlags.ps1 | 86 + README.md | 572 ++++++- TechNetDocumentation_xWebAdministration.html | 1430 ----------------- .../IISServerLevel_Configuration.ps1 | 168 ++ .../MSFT_xIISServerLevelIntegration.Tests.ps1 | 363 +++++ .../MSFT_xWebBindingInformation.Tests.ps1 | 110 ++ .../WebBindingInformation_Config.ps1 | 11 + .../Unit/MSFT_xWebVirtualDirectory.tests.ps1 | 255 +++ Tests/Unit/MSFT_xWebsite.Tests.ps1 | 1290 +++++++++++++++ appveyor.yml | 67 +- xWebAdministration.psd1 | 2 +- 35 files changed, 4616 insertions(+), 1968 deletions(-) create mode 100644 DSCResources/MSFT_xIIsHandler/MSFT_xIisHandler.psm1 create mode 100644 DSCResources/MSFT_xIIsHandler/MSFT_xIisHandler.schema.mof create mode 100644 DSCResources/MSFT_xIisFeatureDelegation/MSFT_xIisFeatureDelegation.psm1 create mode 100644 DSCResources/MSFT_xIisFeatureDelegation/MSFT_xIisFeatureDelegation.schema.mof create mode 100644 DSCResources/MSFT_xIisMimeTypeMapping/MSFT_xIisMimeTypeMapping.psm1 create mode 100644 DSCResources/MSFT_xIisMimeTypeMapping/MSFT_xIisMimeTypeMapping.schema.mof create mode 100644 DSCResources/MSFT_xWebAppPoolDefaults/MSFT_xWebAppPoolDefaults.psm1 create mode 100644 DSCResources/MSFT_xWebAppPoolDefaults/MSFT_xWebAppPoolDefaults.schema.mof create mode 100644 DSCResources/MSFT_xWebSiteDefaults/MSFT_xWebSiteDefaults.psm1 create mode 100644 DSCResources/MSFT_xWebSiteDefaults/MSFT_xWebSiteDefaults.schema.mof create mode 100644 Examples/Sample_xIisFeatureDelegation_AllowSome.ps1 create mode 100644 Examples/Sample_xIisHandler_Remove32Bit.ps1 create mode 100644 Examples/Sample_xIisMimeTypeMapping_RemoveVideo.ps1 create mode 100644 Examples/Sample_xIisServerDefaults.ps1 create mode 100644 Examples/Sample_xWebsite_WithSSLFlags.ps1 delete mode 100644 TechNetDocumentation_xWebAdministration.html create mode 100644 Tests/Integration/IISServerLevel_Configuration.ps1 create mode 100644 Tests/Integration/MSFT_xIISServerLevelIntegration.Tests.ps1 create mode 100644 Tests/Integration/MSFT_xWebBindingInformation.Tests.ps1 create mode 100644 Tests/Integration/WebBindingInformation_Config.ps1 create mode 100644 Tests/Unit/MSFT_xWebVirtualDirectory.tests.ps1 create mode 100644 Tests/Unit/MSFT_xWebsite.Tests.ps1 diff --git a/DSCResources/MSFT_xIIsHandler/MSFT_xIisHandler.psm1 b/DSCResources/MSFT_xIIsHandler/MSFT_xIisHandler.psm1 new file mode 100644 index 000000000..a60d2be90 --- /dev/null +++ b/DSCResources/MSFT_xIIsHandler/MSFT_xIisHandler.psm1 @@ -0,0 +1,263 @@ +###################################################################################### +# DSC Resource for IIS Server level http handlers +###################################################################################### +# There are a few limitations with this resource: +# It only supports builtin handlers, that come with IIS, not third party ones. +# Removing handlers should be no problem, but all new handlers are added at the +# top of the list, meaning, they are tried first. There is no way of ordering the +# handler list except for removing all and then adding them in the correct order. +###################################################################################### +data LocalizedData +{ + # culture="en-US" + ConvertFrom-StringData @' +NoWebAdministrationModule=Please ensure that WebAdministration module is installed. +AddingHandler=Adding handler '{0}' +RemovingHandler=Removing handler '{0}' +HandlerExists=Handler with name '{0}' already exist +HandlerNotPresent=Handler with name '{0}' is not present as requested +HandlerStatusUnknown=Handler with name '{0}' is in an unknown status +HandlerNotSupported=The handler with name '{0}' is not supported. +'@ +} + +###################################################################################### +# The Get-TargetResource cmdlet. +###################################################################################### +function Get-TargetResource +{ + [OutputType([Hashtable])] + param + ( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$Name, + + [Parameter(Mandatory)] + [ValidateSet('Present', 'Absent')] + [string]$Ensure = 'Present' + ) + + # Check if WebAdministration module is present for IIS cmdlets + CheckIISPoshModule + + $handler = GetHandler -name $Name + + if ($handler -eq $null) + { + return @{ + Ensure = 'Absent' + Name = $Name + } + } + else + { + return @{ + Ensure = 'Present' + Name = $Name + } + } +} + +###################################################################################### +# The Set-TargetResource cmdlet. +###################################################################################### +function Set-TargetResource +{ + param + ( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$Name, + + [Parameter(Mandatory)] + [ValidateSet('Present', 'Absent')] + [string]$Ensure = 'Present' + ) + + CheckIISPoshModule + + [string]$psPathRoot = 'MACHINE/WEBROOT/APPHOST' + [string]$sectionNode = 'system.webServer/handlers' + + $handler = GetHandler -name $Name + + if ($handler -eq $null -and $Ensure -eq 'Present') + { + # add the handler + AddHandler -name $Name + Write-Verbose($LocalizedData.AddingHandler -f $Name); + } + elseif ($handler -ne $null -and $Ensure -eq 'Absent') + { + # remove the handler + Remove-WebConfigurationProperty -pspath $psPathRoot -filter $sectionNode -name '.' -AtElement @{name="$Name"} + Write-Verbose($LocalizedData.RemovingHandler -f $Name); + } +} + +###################################################################################### +# The Test-TargetResource cmdlet. +###################################################################################### +function Test-TargetResource +{ + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$Name, + + [Parameter(Mandatory)] + [ValidateSet('Present', 'Absent')] + [string]$Ensure = 'Present' + ) + + [bool]$DesiredConfigurationMatch = $true; + + CheckIISPoshModule + + $handler = GetHandler -name $Name + + if (($handler -eq $null -and $Ensure -eq 'Present') -or ($handler -ne $null -and $Ensure -eq 'Absent')) + { + $DesiredConfigurationMatch = $false; + } + elseif ($handler -ne $null -and $Ensure -eq 'Present') + { + # Already there + Write-Verbose($LocalizedData.HandlerExists -f $Name); + } + elseif ($handler -eq $null -and $Ensure -eq 'Absent') + { + # handler not there and shouldn't be there. + Write-Verbose($LocalizedData.HandlerNotPresent -f $Name); + } + else + { + $DesiredConfigurationMatch = $false; + Write-Verbose($LocalizedData.HandlerStatusUnknown -f $Name); + } + + return $DesiredConfigurationMatch +} + +Function CheckIISPoshModule +{ + # Check if WebAdministration module is present for IIS cmdlets + if(!(Get-Module -ListAvailable -Name WebAdministration)) + { + Throw $LocalizedData.NoWebAdministrationModule + } +} + +Function GetHandler([string]$name) +{ + [string]$filter = "system.webServer/handlers/Add[@Name='" + $name + "']" + return Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter $filter -Name . +} + +Function AddHandler([string]$name) +{ + # using a dictionary of PSObjects, each holding all the information about one handler + $handlers = New-Object 'System.Collections.Generic.Dictionary[string,object]' + # these properties are always the same on all supported versions of Windows + $handlers.Add('ASPClassic',(New-Object PSObject -Property @{name='ASPClassic';path='*.asp';verb='GET,HEAD,POST';modules='IsapiModule';scriptProcessor='%windir%\system32\inetsrv\asp.dll';resourceType='File'})) + $handlers.Add('aspq-Integrated-4.0',(New-Object PSObject -Property @{name='aspq-Integrated-4.0';path='*.aspq';verb='GET,HEAD,POST,DEBUG';type='System.Web.HttpForbiddenHandler';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('aspq-ISAPI-4.0_32bit',(New-Object PSObject -Property @{name='aspq-ISAPI-4.0_32bit';path='*.aspq';verb='*';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('aspq-ISAPI-4.0_64bit',(New-Object PSObject -Property @{name='aspq-ISAPI-4.0_64bit';path='*.aspq';verb='*';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('AssemblyResourceLoader-Integrated-4.0',(New-Object PSObject -Property @{name='AssemblyResourceLoader-Integrated-4.0';path='WebResource.axd';verb='GET,DEBUG';type='System.Web.Handlers.AssemblyResourceLoader';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('AssemblyResourceLoader-Integrated',(New-Object PSObject -Property @{name='AssemblyResourceLoader-Integrated';path='WebResource.axd';verb='GET,DEBUG';type='System.Web.Handlers.AssemblyResourceLoader';preCondition='integratedMode'})) + $handlers.Add('AXD-ISAPI-2.0-64',(New-Object PSObject -Property @{name='AXD-ISAPI-2.0-64';path='*.axd';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv2.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('AXD-ISAPI-2.0',(New-Object PSObject -Property @{name='AXD-ISAPI-2.0';path='*.axd';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv2.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('AXD-ISAPI-4.0_32bit',(New-Object PSObject -Property @{name='AXD-ISAPI-4.0_32bit';path='*.axd';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('AXD-ISAPI-4.0_64bit',(New-Object PSObject -Property @{name='AXD-ISAPI-4.0_64bit';path='*.axd';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('CGI-exe',(New-Object PSObject -Property @{name='CGI-exe';path='*.exe';verb='*';modules='CgiModule';resourceType='File';requireAccess='Execute';allowPathInfo='true'})) + $handlers.Add('ClientLoggingHandler',(New-Object PSObject -Property @{name='ClientLoggingHandler';path='*.log';verb='POST';modules='ClientLoggingHandler';resourceType='Unspecified';requireAccess='None'})) + $handlers.Add('cshtm-Integrated-4.0',(New-Object PSObject -Property @{name='cshtm-Integrated-4.0';path='*.cshtm';verb='GET,HEAD,POST,DEBUG';type='System.Web.HttpForbiddenHandler';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('cshtm-ISAPI-4.0_32bit',(New-Object PSObject -Property @{name='cshtm-ISAPI-4.0_32bit';path='*.cshtm';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('cshtm-ISAPI-4.0_64bit',(New-Object PSObject -Property @{name='cshtm-ISAPI-4.0_64bit';path='*.cshtm';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('cshtml-Integrated-4.0',(New-Object PSObject -Property @{name='cshtml-Integrated-4.0';path='*.cshtml';verb='GET,HEAD,POST,DEBUG';type='System.Web.HttpForbiddenHandler';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('cshtml-ISAPI-4.0_32bit',(New-Object PSObject -Property @{name='cshtml-ISAPI-4.0_32bit';path='*.cshtml';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('cshtml-ISAPI-4.0_64bit',(New-Object PSObject -Property @{name='cshtml-ISAPI-4.0_64bit';path='*.cshtml';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('ExtensionlessUrlHandler-Integrated-4.0',(New-Object PSObject -Property @{name='ExtensionlessUrlHandler-Integrated-4.0';path='*.';verb='GET,HEAD,POST,DEBUG';type='System.Web.Handlers.TransferRequestHandler';preCondition='integratedMode,runtimeVersionv4.0';responseBufferLimit='0'})) + $handlers.Add('ExtensionlessUrlHandler-ISAPI-4.0_32bit',(New-Object PSObject -Property @{name='ExtensionlessUrlHandler-ISAPI-4.0_32bit';path='*.';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('ExtensionlessUrlHandler-ISAPI-4.0_64bit',(New-Object PSObject -Property @{name='ExtensionlessUrlHandler-ISAPI-4.0_64bit';path='*.';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('HttpRemotingHandlerFactory-rem-Integrated-4.0',(New-Object PSObject -Property @{name='HttpRemotingHandlerFactory-rem-Integrated-4.0';path='*.rem';verb='GET,HEAD,POST,DEBUG';type='System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory,;System.Runtime.Remoting,;Version=4.0.0.0,;Culture=neutral,;PublicKeyToken=b77a5c561934e089';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('HttpRemotingHandlerFactory-rem-Integrated',(New-Object PSObject -Property @{name='HttpRemotingHandlerFactory-rem-Integrated';path='*.rem';verb='GET,HEAD,POST,DEBUG';type='System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory,;System.Runtime.Remoting,;Version=2.0.0.0,;Culture=neutral,;PublicKeyToken=b77a5c561934e089';preCondition='integratedMode,runtimeVersionv2.0'})) + $handlers.Add('HttpRemotingHandlerFactory-rem-ISAPI-2.0-64',(New-Object PSObject -Property @{name='HttpRemotingHandlerFactory-rem-ISAPI-2.0-64';path='*.rem';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv2.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('HttpRemotingHandlerFactory-rem-ISAPI-2.0',(New-Object PSObject -Property @{name='HttpRemotingHandlerFactory-rem-ISAPI-2.0';path='*.rem';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv2.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('HttpRemotingHandlerFactory-rem-ISAPI-4.0_32bit',(New-Object PSObject -Property @{name='HttpRemotingHandlerFactory-rem-ISAPI-4.0_32bit';path='*.rem';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('HttpRemotingHandlerFactory-rem-ISAPI-4.0_64bit',(New-Object PSObject -Property @{name='HttpRemotingHandlerFactory-rem-ISAPI-4.0_64bit';path='*.rem';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('HttpRemotingHandlerFactory-soap-Integrated-4.0',(New-Object PSObject -Property @{name='HttpRemotingHandlerFactory-soap-Integrated-4.0';path='*.soap';verb='GET,HEAD,POST,DEBUG';type='System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory,;System.Runtime.Remoting,;Version=4.0.0.0,;Culture=neutral,;PublicKeyToken=b77a5c561934e089';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('HttpRemotingHandlerFactory-soap-Integrated',(New-Object PSObject -Property @{name='HttpRemotingHandlerFactory-soap-Integrated';path='*.soap';verb='GET,HEAD,POST,DEBUG';type='System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory,;System.Runtime.Remoting,;Version=2.0.0.0,;Culture=neutral,;PublicKeyToken=b77a5c561934e089';preCondition='integratedMode,runtimeVersionv2.0'})) + $handlers.Add('HttpRemotingHandlerFactory-soap-ISAPI-2.0-64',(New-Object PSObject -Property @{name='HttpRemotingHandlerFactory-soap-ISAPI-2.0-64';path='*.soap';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv2.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('HttpRemotingHandlerFactory-soap-ISAPI-2.0',(New-Object PSObject -Property @{name='HttpRemotingHandlerFactory-soap-ISAPI-2.0';path='*.soap';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv2.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('HttpRemotingHandlerFactory-soap-ISAPI-4.0_32bit',(New-Object PSObject -Property @{name='HttpRemotingHandlerFactory-soap-ISAPI-4.0_32bit';path='*.soap';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('HttpRemotingHandlerFactory-soap-ISAPI-4.0_64bit',(New-Object PSObject -Property @{name='HttpRemotingHandlerFactory-soap-ISAPI-4.0_64bit';path='*.soap';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('ISAPI-dll',(New-Object PSObject -Property @{name='ISAPI-dll';path='*.dll';verb='*';modules='IsapiModule';resourceType='File';requireAccess='Execute';allowPathInfo='true'})) + $handlers.Add('OPTIONSVerbHandler',(New-Object PSObject -Property @{name='OPTIONSVerbHandler';path='*';verb='OPTIONS';modules='ProtocolSupportModule';requireAccess='None'})) + $handlers.Add('PageHandlerFactory-Integrated-4.0',(New-Object PSObject -Property @{name='PageHandlerFactory-Integrated-4.0';path='*.aspx';verb='GET,HEAD,POST,DEBUG';type='System.Web.UI.PageHandlerFactory';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('PageHandlerFactory-Integrated',(New-Object PSObject -Property @{name='PageHandlerFactory-Integrated';path='*.aspx';verb='GET,HEAD,POST,DEBUG';type='System.Web.UI.PageHandlerFactory';preCondition='integratedMode'})) + $handlers.Add('PageHandlerFactory-ISAPI-2.0-64',(New-Object PSObject -Property @{name='PageHandlerFactory-ISAPI-2.0-64';path='*.aspx';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv2.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('PageHandlerFactory-ISAPI-2.0',(New-Object PSObject -Property @{name='PageHandlerFactory-ISAPI-2.0';path='*.aspx';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv2.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('PageHandlerFactory-ISAPI-4.0_32bit',(New-Object PSObject -Property @{name='PageHandlerFactory-ISAPI-4.0_32bit';path='*.aspx';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('PageHandlerFactory-ISAPI-4.0_64bit',(New-Object PSObject -Property @{name='PageHandlerFactory-ISAPI-4.0_64bit';path='*.aspx';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('rules-Integrated-4.0',(New-Object PSObject -Property @{name='rules-Integrated-4.0';path='*.rules';verb='*';type='System.ServiceModel.Activation.ServiceHttpHandlerFactory,;System.ServiceModel.Activation,;Version=4.0.0.0,;Culture=neutral,;PublicKeyToken=31bf3856ad364e35';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('rules-ISAPI-4.0_32bit',(New-Object PSObject -Property @{name='rules-ISAPI-4.0_32bit';path='*.rules';verb='*';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('rules-ISAPI-4.0_64bit',(New-Object PSObject -Property @{name='rules-ISAPI-4.0_64bit';path='*.rules';verb='*';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('ScriptHandlerFactoryAppServices-Integrated-4.0',(New-Object PSObject -Property @{name='ScriptHandlerFactoryAppServices-Integrated-4.0';path='*_AppService.axd';verb='*';type='System.Web.Script.Services.ScriptHandlerFactory,;System.Web.Extensions,;Version=4.0.0.0,;Culture=neutral,;PublicKeyToken=31BF3856AD364E35';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('ScriptResourceIntegrated-4.0',(New-Object PSObject -Property @{name='ScriptResourceIntegrated-4.0';path='*ScriptResource.axd';verb='GET,HEAD';type='System.Web.Handlers.ScriptResourceHandler,;System.Web.Extensions,;Version=4.0.0.0,;Culture=neutral,;PublicKeyToken=31BF3856AD364E35';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('SecurityCertificate',(New-Object PSObject -Property @{name='SecurityCertificate';path='*.cer';verb='GET,HEAD,POST';modules='IsapiModule';scriptProcessor='%windir%\system32\inetsrv\asp.dll';resourceType='File'})) + $handlers.Add('SimpleHandlerFactory-Integrated-4.0',(New-Object PSObject -Property @{name='SimpleHandlerFactory-Integrated-4.0';path='*.ashx';verb='GET,HEAD,POST,DEBUG';type='System.Web.UI.SimpleHandlerFactory';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('SimpleHandlerFactory-Integrated',(New-Object PSObject -Property @{name='SimpleHandlerFactory-Integrated';path='*.ashx';verb='GET,HEAD,POST,DEBUG';type='System.Web.UI.SimpleHandlerFactory';preCondition='integratedMode'})) + $handlers.Add('SimpleHandlerFactory-ISAPI-2.0-64',(New-Object PSObject -Property @{name='SimpleHandlerFactory-ISAPI-2.0-64';path='*.ashx';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv2.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('SimpleHandlerFactory-ISAPI-2.0',(New-Object PSObject -Property @{name='SimpleHandlerFactory-ISAPI-2.0';path='*.ashx';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv2.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('SimpleHandlerFactory-ISAPI-4.0_32bit',(New-Object PSObject -Property @{name='SimpleHandlerFactory-ISAPI-4.0_32bit';path='*.ashx';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('SimpleHandlerFactory-ISAPI-4.0_64bit',(New-Object PSObject -Property @{name='SimpleHandlerFactory-ISAPI-4.0_64bit';path='*.ashx';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('SSINC-shtm',(New-Object PSObject -Property @{name='SSINC-shtm';path='*.shtm';verb='GET,HEAD,POST';modules='ServerSideIncludeModule';resourceType='File'})) + $handlers.Add('SSINC-shtml',(New-Object PSObject -Property @{name='SSINC-shtml';path='*.shtml';verb='GET,HEAD,POST';modules='ServerSideIncludeModule';resourceType='File'})) + $handlers.Add('SSINC-stm',(New-Object PSObject -Property @{name='SSINC-stm';path='*.stm';verb='GET,HEAD,POST';modules='ServerSideIncludeModule';resourceType='File'})) + $handlers.Add('StaticFile',(New-Object PSObject -Property @{name='StaticFile';path='*';verb='*';modules='StaticFileModule,DefaultDocumentModule,DirectoryListingModule';resourceType='Either';requireAccess='Read'})) + $handlers.Add('svc-Integrated-4.0',(New-Object PSObject -Property @{name='svc-Integrated-4.0';path='*.svc';verb='*';type='System.ServiceModel.Activation.ServiceHttpHandlerFactory,;System.ServiceModel.Activation,;Version=4.0.0.0,;Culture=neutral,;PublicKeyToken=31bf3856ad364e35';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('svc-ISAPI-4.0_32bit',(New-Object PSObject -Property @{name='svc-ISAPI-4.0_32bit';path='*.svc';verb='*';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('svc-ISAPI-4.0_64bit',(New-Object PSObject -Property @{name='svc-ISAPI-4.0_64bit';path='*.svc';verb='*';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('TraceHandler-Integrated-4.0',(New-Object PSObject -Property @{name='TraceHandler-Integrated-4.0';path='trace.axd';verb='GET,HEAD,POST,DEBUG';type='System.Web.Handlers.TraceHandler';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('TraceHandler-Integrated',(New-Object PSObject -Property @{name='TraceHandler-Integrated';path='trace.axd';verb='GET,HEAD,POST,DEBUG';type='System.Web.Handlers.TraceHandler';preCondition='integratedMode'})) + $handlers.Add('TRACEVerbHandler',(New-Object PSObject -Property @{name='TRACEVerbHandler';path='*';verb='TRACE';modules='ProtocolSupportModule';requireAccess='None'})) + $handlers.Add('vbhtm-Integrated-4.0',(New-Object PSObject -Property @{name='vbhtm-Integrated-4.0';path='*.vbhtm';verb='GET,HEAD,POST,DEBUG';type='System.Web.HttpForbiddenHandler';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('vbhtm-ISAPI-4.0_32bit',(New-Object PSObject -Property @{name='vbhtm-ISAPI-4.0_32bit';path='*.vbhtm';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('vbhtm-ISAPI-4.0_64bit',(New-Object PSObject -Property @{name='vbhtm-ISAPI-4.0_64bit';path='*.vbhtm';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('vbhtml-Integrated-4.0',(New-Object PSObject -Property @{name='vbhtml-Integrated-4.0';path='*.vbhtml';verb='GET,HEAD,POST,DEBUG';type='System.Web.HttpForbiddenHandler';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('vbhtml-ISAPI-4.0_32bit',(New-Object PSObject -Property @{name='vbhtml-ISAPI-4.0_32bit';path='*.vbhtml';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('vbhtml-ISAPI-4.0_64bit',(New-Object PSObject -Property @{name='vbhtml-ISAPI-4.0_64bit';path='*.vbhtml';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('WebAdminHandler-Integrated-4.0',(New-Object PSObject -Property @{name='WebAdminHandler-Integrated-4.0';path='WebAdmin.axd';verb='GET,DEBUG';type='System.Web.Handlers.WebAdminHandler';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('WebAdminHandler-Integrated',(New-Object PSObject -Property @{name='WebAdminHandler-Integrated';path='WebAdmin.axd';verb='GET,DEBUG';type='System.Web.Handlers.WebAdminHandler';preCondition='integratedMode'})) + $handlers.Add('WebDAV',(New-Object PSObject -Property @{name='WebDAV';path='*';verb='PROPFIND,PROPPATCH,MKCOL,PUT,COPY,DELETE,MOVE,LOCK,UNLOCK';modules='WebDAVModule';resourceType='Unspecified';requireAccess='None'})) + $handlers.Add('WebServiceHandlerFactory-Integrated-4.0',(New-Object PSObject -Property @{name='WebServiceHandlerFactory-Integrated-4.0';path='*.asmx';verb='GET,HEAD,POST,DEBUG';type='System.Web.Script.Services.ScriptHandlerFactory,;System.Web.Extensions,;Version=4.0.0.0,;Culture=neutral,;PublicKeyToken=31bf3856ad364e35';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('WebServiceHandlerFactory-Integrated',(New-Object PSObject -Property @{name='WebServiceHandlerFactory-Integrated';path='*.asmx';verb='GET,HEAD,POST,DEBUG';type='System.Web.Services.Protocols.WebServiceHandlerFactory,;System.Web.Services,;Version=2.0.0.0,;Culture=neutral,;PublicKeyToken=b03f5f7f11d50a3a';preCondition='integratedMode,runtimeVersionv2.0'})) + $handlers.Add('WebServiceHandlerFactory-ISAPI-2.0-64',(New-Object PSObject -Property @{name='WebServiceHandlerFactory-ISAPI-2.0-64';path='*.asmx';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv2.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('WebServiceHandlerFactory-ISAPI-2.0',(New-Object PSObject -Property @{name='WebServiceHandlerFactory-ISAPI-2.0';path='*.asmx';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv2.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('WebServiceHandlerFactory-ISAPI-4.0_32bit',(New-Object PSObject -Property @{name='WebServiceHandlerFactory-ISAPI-4.0_32bit';path='*.asmx';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('WebServiceHandlerFactory-ISAPI-4.0_64bit',(New-Object PSObject -Property @{name='WebServiceHandlerFactory-ISAPI-4.0_64bit';path='*.asmx';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('xamlx-Integrated-4.0',(New-Object PSObject -Property @{name='xamlx-Integrated-4.0';path='*.xamlx';verb='GET,HEAD,POST,DEBUG';type='System.Xaml.Hosting.XamlHttpHandlerFactory,;System.Xaml.Hosting,;Version=4.0.0.0,;Culture=neutral,;PublicKeyToken=31bf3856ad364e35';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('xamlx-ISAPI-4.0_32bit',(New-Object PSObject -Property @{name='xamlx-ISAPI-4.0_32bit';path='*.xamlx';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('xamlx-ISAPI-4.0_64bit',(New-Object PSObject -Property @{name='xamlx-ISAPI-4.0_64bit';path='*.xamlx';verb='GET,HEAD,POST,DEBUG';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness64';responseBufferLimit='0'})) + $handlers.Add('xoml-Integrated-4.0',(New-Object PSObject -Property @{name='xoml-Integrated-4.0';path='*.xoml';verb='*';type='System.ServiceModel.Activation.ServiceHttpHandlerFactory,;System.ServiceModel.Activation,;Version=4.0.0.0,;Culture=neutral,;PublicKeyToken=31bf3856ad364e35';preCondition='integratedMode,runtimeVersionv4.0'})) + $handlers.Add('xoml-ISAPI-4.0_32bit',(New-Object PSObject -Property @{name='xoml-ISAPI-4.0_32bit';path='*.xoml';verb='*';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness32';responseBufferLimit='0'})) + $handlers.Add('xoml-ISAPI-4.0_64bit',(New-Object PSObject -Property @{name='xoml-ISAPI-4.0_64bit';path='*.xoml';verb='*';modules='IsapiModule';scriptProcessor='%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll';preCondition='classicMode,runtimeVersionv4.0,bitness64';responseBufferLimit='0'})) + + # check whether our dictionary has an item with the specified key + if ($handlers.ContainsKey($name)) + { + # add the new handler + Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter 'system.webServer/handlers' -name '.' -value $handlers[$name] + } + else + { + Throw ($LocalizedData.HandlerNotSupported -f $Name); + } +} + +# FUNCTIONS TO BE EXPORTED +Export-ModuleMember -Function *-TargetResource diff --git a/DSCResources/MSFT_xIIsHandler/MSFT_xIisHandler.schema.mof b/DSCResources/MSFT_xIIsHandler/MSFT_xIisHandler.schema.mof new file mode 100644 index 000000000..3541a39ae --- /dev/null +++ b/DSCResources/MSFT_xIIsHandler/MSFT_xIisHandler.schema.mof @@ -0,0 +1,6 @@ +[ClassVersion("1.0.0"), FriendlyName("xIisHandler")] +class MSFT_xIisHandler : OMI_BaseResource +{ + [Key] string Name; + [Required,ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] string Ensure; +}; diff --git a/DSCResources/MSFT_xIisFeatureDelegation/MSFT_xIisFeatureDelegation.psm1 b/DSCResources/MSFT_xIisFeatureDelegation/MSFT_xIisFeatureDelegation.psm1 new file mode 100644 index 000000000..d6e4411ef --- /dev/null +++ b/DSCResources/MSFT_xIisFeatureDelegation/MSFT_xIisFeatureDelegation.psm1 @@ -0,0 +1,163 @@ +###################################################################################### +# DSC Resource for IIS Server level Feature Delegation +###################################################################################### + +data LocalizedData +{ + # culture="en-US" + ConvertFrom-StringData @' +NoWebAdministrationModule=Please ensure that WebAdministration module is installed. +UnableToGetConfig=Unable to get configuration data for '{0}' +ChangedMessage=Changed overrideMode for '{0}' to {1} +'@ +} + +###################################################################################### +# The Get-TargetResource cmdlet. +# This function will get the Mime type for a file extension +###################################################################################### +function Get-TargetResource +{ + [OutputType([Hashtable])] + param + ( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$SectionName, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [ValidateSet('Allow', 'Deny')] + [String]$OverrideMode + ) + + CheckIISPoshModule + + [string]$oMode = GetOverrideMode -section $SectionName + + if ($oMode -eq $null) + { + $ensureResult = 'Absent'; + } + else + { + if ($oMode -eq $OverrideMode) + { + $ensureResult = 'Present' + } + else + { + $ensureResult = 'Absent'; + } + } + + # in case the section has not been found, $oMode will be $null + $getTargetResourceResult = @{SectionName = $SectionName + OverrideMode = $oMode + Ensure = $ensureResult} + + + return $getTargetResourceResult +} + +###################################################################################### +# The Set-TargetResource cmdlet. +# This function set the OverrideMode for a given section if not already correct +###################################################################################### +function Set-TargetResource +{ + param + ( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$SectionName, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [ValidateSet('Allow', 'Deny')] + [String]$OverrideMode + ) + + CheckIISPoshModule + [string]$oMode = GetOverrideMode -section $SectionName + + + if ($oMode -eq 'Allow' -and $OverrideMode -eq 'Deny') + { + Set-webconfiguration -Location '' -Filter "/system.webServer/$SectionName" -PSPath 'machine/webroot/apphost' -metadata overrideMode -value Deny + Write-Verbose($($LocalizedData.ChangedMessage) -f $SectionName,'Deny') + } + elseif ($oMode -eq 'Deny' -and $OverrideMode -eq 'Allow') + { + Set-webconfiguration -Location '' -Filter "/system.webServer/$SectionName" -PSPath 'machine/webroot/apphost' -metadata overrideMode -value Allow + Write-Verbose($($LocalizedData.ChangedMessage) -f $SectionName,'Allow') + } +} + +###################################################################################### +# The Test-TargetResource cmdlet. +# This will test if the given section has the required OverrideMode +###################################################################################### +function Test-TargetResource +{ + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$SectionName, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [ValidateSet('Allow', 'Deny')] + [String]$OverrideMode + ) + + CheckIISPoshModule + + [string]$oMode = GetOverrideMode -section $SectionName + + if ($oMode -eq $OverrideMode) + { + # in this case we have our desired state + return $true + } + else + { + # state doesn't match or doesn't exist + return $false + } +} + +Function CheckIISPoshModule +{ + # Check if WebAdministration module is present for IIS cmdlets + if(!(Get-Module -ListAvailable -Name WebAdministration)) + { + Throw $LocalizedData.NoWebAdministrationModule + } +} + +Function GetOverrideMode([string]$section) +{ + $errorMessage = $($LocalizedData.UnableToGetConfig) -f $section + if ((Get-WebConfiguration -Location '' -Filter /system.webServer/$section).count -eq 0) + { + Throw $errorMessage; + } + + [string]$oMode = ((Get-WebConfiguration -Location '' -Filter /system.webServer/$section -metadata).Metadata).effectiveOverrideMode + + # check for a single value. + # if $oMode is anything but Allow or Deny, we have a problem with our get-webconfiguration call + # or the ApplicationHost.config file is corrupted, I think its worth stopping here. + if ($oMode -notmatch "^(Allow|Deny)$") + { + Throw $errorMessage + } + + return $oMode +} + +# FUNCTIONS TO BE EXPORTED +Export-ModuleMember -function Get-TargetResource, Set-TargetResource, Test-TargetResource diff --git a/DSCResources/MSFT_xIisFeatureDelegation/MSFT_xIisFeatureDelegation.schema.mof b/DSCResources/MSFT_xIisFeatureDelegation/MSFT_xIisFeatureDelegation.schema.mof new file mode 100644 index 000000000..329a4a355 --- /dev/null +++ b/DSCResources/MSFT_xIisFeatureDelegation/MSFT_xIisFeatureDelegation.schema.mof @@ -0,0 +1,6 @@ +[ClassVersion("1.0.0"), FriendlyName("xIisFeatureDelegation")] +class MSFT_xIisFeatureDelegation : OMI_BaseResource +{ + [Key] string SectionName; + [Key,ValueMap{"Allow", "Deny"},Values{"Allow", "Deny"}] string OverrideMode; +}; diff --git a/DSCResources/MSFT_xIisMimeTypeMapping/MSFT_xIisMimeTypeMapping.psm1 b/DSCResources/MSFT_xIisMimeTypeMapping/MSFT_xIisMimeTypeMapping.psm1 new file mode 100644 index 000000000..cdf87fb3b --- /dev/null +++ b/DSCResources/MSFT_xIisMimeTypeMapping/MSFT_xIisMimeTypeMapping.psm1 @@ -0,0 +1,171 @@ +###################################################################################### +# DSC Resource for IIS Server level MIME Type mappings +###################################################################################### +data LocalizedData +{ + # culture="en-US" + ConvertFrom-StringData @' +NoWebAdministrationModule=Please ensure that WebAdministration module is installed. +AddingType=Adding MIMEType '{0}' for extension '{1}' +RemovingType=Removing MIMEType '{0}' for extension '{1}' +TypeExists=MIMEType '{0}' for extension '{1}' already exist +TypeNotPresent=MIMEType '{0}' for extension '{1}' is not present as requested +TypeStatusUnknown=MIMEType '{0}' for extension '{1}' is is an unknown status +'@ +} + +###################################################################################### +# The Get-TargetResource cmdlet. +# This function will get the Mime type for a file extension +###################################################################################### +function Get-TargetResource +{ + [OutputType([Hashtable])] + param + ( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$Extension, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$MimeType, + + [ValidateSet('Present', 'Absent')] + [Parameter(Mandatory)] + [string]$Ensure + ) + + # Check if WebAdministration module is present for IIS cmdlets + CheckIISPoshModule + + $mt = GetMapping -extension $Extension -type $MimeType + + if ($mt -eq $null) + { + return @{ + Ensure = 'Absent' + Extension = $null + MimeType = $null + } + } + else + { + return @{ + Ensure = 'Present' + Extension = $mt.fileExtension + MimeType = $mt.mimeType + } + } +} + +###################################################################################### +# The Set-TargetResource cmdlet. +# This function will add or remove a MIME type mapping +###################################################################################### +function Set-TargetResource +{ + param + ( + [ValidateSet('Present', 'Absent')] + [Parameter(Mandatory)] + [string]$Ensure = 'Present', + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$Extension, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$MimeType + ) + + CheckIISPoshModule + + [string]$psPathRoot = 'MACHINE/WEBROOT/APPHOST' + [string]$sectionNode = 'system.webServer/staticContent' + + $mt = GetMapping -extension $Extension -type $MimeType + + if ($mt -eq $null -and $Ensure -eq 'Present') + { + # add the MimeType + Add-WebConfigurationProperty -pspath $psPathRoot -filter $sectionNode -name '.' -value @{fileExtension="$Extension";mimeType="$MimeType"} + Write-Verbose($LocalizedData.AddingType -f $MimeType,$Extension); + } + elseif ($mt -ne $null -and $Ensure -eq 'Absent') + { + # remove the MimeType + Remove-WebConfigurationProperty -pspath $psPathRoot -filter $sectionNode -name '.' -AtElement @{fileExtension="$Extension"} + Write-Verbose($LocalizedData.RemovingType -f $MimeType,$Extension); + } +} + +###################################################################################### +# The Test-TargetResource cmdlet. +# This will test if the given MIME type mapping has the desired state, Present or Absent +###################################################################################### +function Test-TargetResource +{ + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory)] + [ValidateSet('Present', 'Absent')] + [string]$Ensure = 'Present', + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$Extension, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$MimeType + ) + + [bool]$DesiredConfigurationMatch = $true; + + CheckIISPoshModule + + $mt = GetMapping -extension $Extension -type $MimeType + + if (($mt -eq $null -and $Ensure -eq 'Present') -or ($mt -ne $null -and $Ensure -eq 'Absent')) + { + $DesiredConfigurationMatch = $false; + } + elseif ($mt -ne $null -and $Ensure -eq 'Present') + { + # Already there + Write-Verbose($LocalizedData.TypeExists -f $MimeType,$Extension); + } + elseif ($mt -eq $null -and $Ensure -eq 'Absent') + { + # TypeNotPresent + Write-Verbose($LocalizedData.TypeNotPresent -f $MimeType,$Extension); + } + else + { + $DesiredConfigurationMatch = $false; + Write-Verbose($LocalizedData.TypeStatusUnknown -f $MimeType,$Extension); + } + + return $DesiredConfigurationMatch +} + +Function CheckIISPoshModule +{ + # Check if WebAdministration module is present for IIS cmdlets + if(!(Get-Module -ListAvailable -Name WebAdministration)) + { + Throw $LocalizedData.NoWebAdministrationModule + } +} + +Function GetMapping([string]$extension,[string]$type) +{ + [string]$filter = "system.webServer/staticContent/mimeMap[@fileExtension='" + $extension + "' and @mimeType='" + $type + "']" + return Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter $filter -Name . +} + +# FUNCTIONS TO BE EXPORTED +Export-ModuleMember -function Get-TargetResource, Set-TargetResource, Test-TargetResource diff --git a/DSCResources/MSFT_xIisMimeTypeMapping/MSFT_xIisMimeTypeMapping.schema.mof b/DSCResources/MSFT_xIisMimeTypeMapping/MSFT_xIisMimeTypeMapping.schema.mof new file mode 100644 index 000000000..1dadb3892 --- /dev/null +++ b/DSCResources/MSFT_xIisMimeTypeMapping/MSFT_xIisMimeTypeMapping.schema.mof @@ -0,0 +1,7 @@ +[ClassVersion("1.0.0"), FriendlyName("xIisMimeTypeMapping")] +class MSFT_xIisMimeTypeMapping : OMI_BaseResource +{ + [Key] string Extension; + [Key] string MimeType; + [Required,ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] string Ensure; +}; diff --git a/DSCResources/MSFT_xIisModule/MSFT_xIisModule.psm1 b/DSCResources/MSFT_xIisModule/MSFT_xIisModule.psm1 index 8a9b5be41..745088087 100644 --- a/DSCResources/MSFT_xIisModule/MSFT_xIisModule.psm1 +++ b/DSCResources/MSFT_xIisModule/MSFT_xIisModule.psm1 @@ -43,11 +43,11 @@ function Get-IisSitePath if(-not $SiteName) { - return "IIS:\" + return 'IIS:\' } else { - return Join-Path "IIS:\sites\" $SiteName + return Join-Path 'IIS:\sites\' $SiteName } } @@ -65,7 +65,7 @@ function Get-IisHandler ) Trace-Message "Getting Handler for $Name in Site $SiteName" - return get-webconfiguration -Filter "System.WebServer/handlers/*" -PSPath (Get-IisSitePath -SiteName $SiteName) | ?{$_.Name -ieq $Name} + return get-webconfiguration -Filter 'System.WebServer/handlers/*' -PSPath (Get-IisSitePath -SiteName $SiteName) | ?{$_.Name -ieq $Name} } # Remove an IIS Handler @@ -115,16 +115,16 @@ function Get-TargetResource [System.String[]] $Verb, - [ValidateSet("FastCgiModule")] + [ValidateSet('FastCgiModule')] [System.String] - $ModuleType = "FastCgiModule", + $ModuleType = 'FastCgiModule', [System.String] $SiteName ) $currentVerbs = @() - $Ensure = "Absent" + $Ensure = 'Absent' $getTargetResourceResult = $null; $modulePresent = $false; @@ -133,7 +133,7 @@ function Get-TargetResource if($handler ) { - $Ensure = "Present" + $Ensure = 'Present' $modulePresent = $true; } @@ -190,7 +190,7 @@ function Get-GetParameters $getParameters = @{} foreach($key in $functionParameters.Keys) { - if($key -ine "Ensure") + if($key -ine 'Ensure') { $getParameters.Add($key, $functionParameters.$key) | Out-Null } @@ -224,13 +224,13 @@ function Set-TargetResource [System.String] $SiteName, - [ValidateSet("Present","Absent")] + [ValidateSet('Present','Absent')] [System.String] $Ensure, - [ValidateSet("FastCgiModule")] + [ValidateSet('FastCgiModule')] [System.String] - $ModuleType = "FastCgiModule" + $ModuleType = 'FastCgiModule' ) $GetParameters = Get-GetParameters -functionParameters $PSBoundParameters $resourceStatus = Get-TargetResource @GetParameters @@ -240,23 +240,23 @@ function Set-TargetResource return } - Trace-Message "Get complete" + Trace-Message 'Get complete' - if($Ensure -eq "Present") + if($Ensure -eq 'Present') { if($resourceTests.ModulePresent -and -not $resourceTests.ModuleConfigured) { - Trace-Message "Removing handler..." + Trace-Message 'Removing handler...' Remove-IisHandler } if(-not $resourceTests.ModulePresent -or -not $resourceTests.ModuleConfigured) { - Trace-Message "Adding handler..." + Trace-Message 'Adding handler...' add-webconfiguration /system.webServer/handlers iis:\ -value @{ name = $Name path = $RequestPath - verb = $Verb -join "," + verb = $Verb -join ',' modules = $ModuleType scriptProcessor = $Path } @@ -265,7 +265,7 @@ function Set-TargetResource # bug(TBD) deal with this better, maybe a seperate resource.... if(-not $resourceTests.EndPointSetup) { - Trace-Message "Adding fastCgi..." + Trace-Message 'Adding fastCgi...' add-WebConfiguration /system.webServer/fastCgi iis:\ -value @{ fullPath = $Path } @@ -304,13 +304,13 @@ function Test-TargetResource [System.String] $SiteName, - [ValidateSet("Present","Absent")] + [ValidateSet('Present','Absent')] [System.String] $Ensure, - [ValidateSet("FastCgiModule")] + [ValidateSet('FastCgiModule')] [System.String] - $ModuleType = "FastCgiModule" + $ModuleType = 'FastCgiModule' ) $GetParameters = Get-GetParameters -functionParameters $PSBoundParameters @@ -342,14 +342,14 @@ function Test-TargetResourceImpl [System.String[]] $Verb, - [ValidateSet("FastCgiModule")] + [ValidateSet('FastCgiModule')] [System.String] - $ModuleType = "FastCgiModule", + $ModuleType = 'FastCgiModule', [System.String] $SiteName, - [ValidateSet("Present","Absent")] + [ValidateSet('Present','Absent')] [System.String] $Ensure, diff --git a/DSCResources/MSFT_xWebAppPoolDefaults/MSFT_xWebAppPoolDefaults.psm1 b/DSCResources/MSFT_xWebAppPoolDefaults/MSFT_xWebAppPoolDefaults.psm1 new file mode 100644 index 000000000..fa507b465 --- /dev/null +++ b/DSCResources/MSFT_xWebAppPoolDefaults/MSFT_xWebAppPoolDefaults.psm1 @@ -0,0 +1,160 @@ +###################################################################################### +# DSC Resource for IIS Server level Application Ppol Defaults +# ApplicationHost.config: system.applicationHost/applicationPools +# +# only a limited number of settings are supported at this time +# We try to cover the most common use cases +# We have a single parameter for each setting +###################################################################################### +data LocalizedData +{ + # culture="en-US" + ConvertFrom-StringData @' +NoWebAdministrationModule=Please ensure that WebAdministration module is installed. +SettingValue=Changing default value '{0}' to '{1}' +ValueOk=Default value '{0}' is already '{1}' +'@ +} + +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory)] + [ValidateSet('Machine')] + [string]$ApplyTo + ) + + # Check if WebAdministration module is present for IIS cmdlets + CheckIISPoshModule + + return @{ManagedRuntimeVersion = (GetValue -Path '' -Name 'managedRuntimeVersion') + IdentityType = ( GetValue -Path 'processModel' -Name 'identityType')} +} + + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [ValidateSet('Machine')] + [parameter(Mandatory = $true)] + [string]$ApplyTo, + # in the future there will be another CLR version to be allowed + [ValidateSet('','v2.0','v4.0')] + [string]$ManagedRuntimeVersion, + # TODO: we currently don't allow a custom identity + [ValidateSet('ApplicationPoolIdentity','LocalService','LocalSystem','NetworkService')] + [string]$IdentityType + ) + + CheckIISPoshModule + + SetValue -Path '' -Name 'managedRuntimeVersion' -NewValue $ManagedRuntimeVersion + SetValue -Path 'processModel' -Name 'identityType' -NewValue $IdentityType +} + + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [ValidateSet('Machine')] + [parameter(Mandatory = $true)] + [string]$ApplyTo, + [ValidateSet('','v2.0','v4.0')] + [string]$ManagedRuntimeVersion, + [ValidateSet('ApplicationPoolIdentity','LocalService','LocalSystem','NetworkService')] + [string]$IdentityType + ) + + CheckIISPoshModule + + if (!(CheckValue -Path '' -Name 'managedRuntimeVersion' -NewValue $ManagedRuntimeVersion)) + { + return $false + } + + if (!(CheckValue -Path 'processModel' -Name 'identityType' -NewValue $IdentityType)) + { + return $false + } + + return $true +} + +###################################################################################### +# Helper Functions +###################################################################################### + +Function CheckValue([string]$path,[string]$name,[string]$newValue) +{ + + if (!$newValue) + { + # if no new value was specified, we assume this value is okay. + return $true + } + + $existingValue = GetValue -Path $path -Name $name + if ($existingValue -ne $newValue) + { + return $false + } + else + { + $relPath = $path + '/' + $name + Write-Verbose($LocalizedData.ValueOk -f $relPath,$newValue); + return $true + } +} + +# some internal helper function to do the actual work: + +Function SetValue([string]$path,[string]$name,[string]$newValue) +{ + # if the variable doesn't exist, the user doesn't want to change this value + if (!$newValue) + { + return + } + + $existingValue = GetValue -Path $path -Name $name + if ($existingValue -ne $newValue) + { + if ($path -ne '') + { + $path = '/' + $path + } + + Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.applicationHost/applicationPools/applicationPoolDefaults$path" -name $name -value "$newValue" + $relPath = $path + '/' + $name + Write-Verbose($LocalizedData.SettingValue -f $relPath,$newValue); + } +} + +Function GetValue([string]$path,[string]$name) +{ + if ($path -ne '') + { + $path = '/' + $path + } + + return Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.applicationHost/applicationPools/applicationPoolDefaults$path" -name $name +} + +Function CheckIISPoshModule +{ + # Check if WebAdministration module is present for IIS cmdlets + if(!(Get-Module -ListAvailable -Name WebAdministration)) + { + Throw $LocalizedData.NoWebAdministrationModule + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/DSCResources/MSFT_xWebAppPoolDefaults/MSFT_xWebAppPoolDefaults.schema.mof b/DSCResources/MSFT_xWebAppPoolDefaults/MSFT_xWebAppPoolDefaults.schema.mof new file mode 100644 index 000000000..a8df17059 --- /dev/null +++ b/DSCResources/MSFT_xWebAppPoolDefaults/MSFT_xWebAppPoolDefaults.schema.mof @@ -0,0 +1,8 @@ + +[ClassVersion("1.0.0.0"), FriendlyName("xWebAppPoolDefaults")] +class MSFT_xWebAppPoolDefaults : OMI_BaseResource +{ + [Key, Description("Dummy value because we need a key, always 'Machine'"), ValueMap{"Machine"}, Values{"Machine"}] string ApplyTo; + [write, Description("applicationPools/applicationPoolDefaults/managedRuntimeVersion"), ValueMap{"","v2.0","v4.0"}, Values{"","v2.0","v4.0"}] string ManagedRuntimeVersion; + [write, Description("applicationPools/applicationPoolDefaults/processModel/identityType"), ValueMap{"ApplicationPoolIdentity","LocalService","LocalSystem","NetworkService"}, Values{"ApplicationPoolIdentity","LocalService","LocalSystem","NetworkService"}] string IdentityType; +}; diff --git a/DSCResources/MSFT_xWebApplication/MSFT_xWebApplication.psm1 b/DSCResources/MSFT_xWebApplication/MSFT_xWebApplication.psm1 index 7235e5988..97db0255c 100644 --- a/DSCResources/MSFT_xWebApplication/MSFT_xWebApplication.psm1 +++ b/DSCResources/MSFT_xWebApplication/MSFT_xWebApplication.psm1 @@ -25,15 +25,15 @@ function Get-TargetResource $webApplication = Get-WebApplication -Site $Website -Name $Name - $PhysicalPath = "" - $Ensure = "Absent" - $WebAppPool = "" + $PhysicalPath = '' + $Ensure = 'Absent' + $WebAppPool = '' if ($webApplication.Count -eq 1) { $PhysicalPath = $webApplication.PhysicalPath $WebAppPool = $webApplication.applicationPool - $Ensure = "Present" + $Ensure = 'Present' } $returnValue = @{ @@ -69,14 +69,14 @@ function Set-TargetResource [System.String] $PhysicalPath, - [ValidateSet("Present","Absent")] + [ValidateSet('Present','Absent')] [System.String] - $Ensure = "Present" + $Ensure = 'Present' ) CheckDependencies - if ($Ensure -eq "Present") + if ($Ensure -eq 'Present') { $webApplication = Get-WebApplication -Site $Website -Name $Name if ($webApplication.count -eq 0) @@ -99,7 +99,7 @@ function Set-TargetResource } } - if ($Ensure -eq "Absent") + if ($Ensure -eq 'Absent') { Write-Verbose "Removing existing Web Application $Name." Remove-WebApplication -Site $Website -Name $Name @@ -129,16 +129,16 @@ function Test-TargetResource [System.String] $PhysicalPath, - [ValidateSet("Present","Absent")] + [ValidateSet('Present','Absent')] [System.String] - $Ensure = "Present" + $Ensure = 'Present' ) CheckDependencies $webApplication = Get-WebApplication -Site $Website -Name $Name - if ($webApplication.count -eq 1 -and $Ensure -eq "Present") { + if ($webApplication.count -eq 1 -and $Ensure -eq 'Present') { if ($webApplication.physicalPath -ne $PhysicalPath) { Write-Verbose "Physical path for web application $Name does not match desired state." @@ -151,12 +151,12 @@ function Test-TargetResource } else { - Write-Verbose "Web application pool matches desired state." + Write-Verbose 'Web application pool matches desired state.' return $true } } - if ($webApplication.count -eq 0 -and $Ensure -eq "Absent") { + if ($webApplication.count -eq 0 -and $Ensure -eq 'Absent') { Write-Verbose "Web application $Name should be absent and is absent." return $true } @@ -166,11 +166,11 @@ function Test-TargetResource function CheckDependencies { - Write-Verbose "Checking whether WebAdministration is there in the machine or not." + Write-Verbose 'Checking whether WebAdministration is there in the machine or not.' # Check if WebAdministration module is present for IIS cmdlets if(!(Get-Module -ListAvailable -Name WebAdministration)) { - Throw "Please ensure that WebAdministration module is installed." + Throw 'Please ensure that WebAdministration module is installed.' } } diff --git a/DSCResources/MSFT_xWebConfigKeyValue/MSFT_xWebConfigKeyValue.psm1 b/DSCResources/MSFT_xWebConfigKeyValue/MSFT_xWebConfigKeyValue.psm1 index 7d4d794a3..d07047de4 100644 --- a/DSCResources/MSFT_xWebConfigKeyValue/MSFT_xWebConfigKeyValue.psm1 +++ b/DSCResources/MSFT_xWebConfigKeyValue/MSFT_xWebConfigKeyValue.psm1 @@ -9,7 +9,7 @@ function Get-TargetResource $WebsitePath, [parameter(Mandatory = $true)] - [ValidateSet("AppSettings")] + [ValidateSet('AppSettings')] [System.String] $ConfigSection, @@ -27,14 +27,14 @@ function Get-TargetResource if($existingvalue.Length -eq 0) { return @{ - Ensure = "Absent" + Ensure = 'Absent' Key = $Key Value = $existingvalue } } return @{ - Ensure = "Present" + Ensure = 'Present' Key = $Key Value = $existingvalue } @@ -51,13 +51,13 @@ function Set-TargetResource $WebsitePath, [parameter(Mandatory = $true)] - [ValidateSet("AppSettings")] + [ValidateSet('AppSettings')] [System.String] $ConfigSection, - [ValidateSet("Present","Absent")] + [ValidateSet('Present','Absent')] [System.String] - $Ensure = "Present", + $Ensure = 'Present', [parameter(Mandatory = $true)] [String] @@ -70,7 +70,7 @@ function Set-TargetResource $IsAttribute ) - if($Ensure -eq "Present") + if($Ensure -eq 'Present') { $existingvalue = Get-ItemValue -key $Key -isAttribute $IsAttribute -websitePath $WebsitePath -configSection $ConfigSection @@ -80,7 +80,7 @@ function Set-TargetResource } else { - $propertyName ="value" + $propertyName ='value' if($IsAttribute) { $propertyName = $Key @@ -105,13 +105,13 @@ function Test-TargetResource $WebsitePath, [parameter(Mandatory = $true)] - [ValidateSet("AppSettings")] + [ValidateSet('AppSettings')] [System.String] $ConfigSection, - [ValidateSet("Present","Absent")] + [ValidateSet('Present','Absent')] [System.String] - $Ensure = "Present", + $Ensure = 'Present', [parameter(Mandatory = $true)] [String] @@ -131,7 +131,7 @@ function Test-TargetResource $existingvalue = Get-ItemValue -key $Key -isAttribute $IsAttribute -websitePath $WebsitePath -configSection $ConfigSection - if($Ensure -eq "Present") + if($Ensure -eq 'Present') { if(!$IsAttribute) { @@ -192,7 +192,7 @@ function Add-item([string]$key, [string]$value, [Boolean]$isAttribute, [string]$ if(!$isAttribute) { - Add-WebConfigurationProperty -filter $defaultFilter -name "." -value $itemCollection -PSPath $websitePath + Add-WebConfigurationProperty -filter $defaultFilter -name '.' -value $itemCollection -PSPath $websitePath } else { @@ -233,11 +233,11 @@ function Remove-Item([string]$key, [Boolean]$isAttribute, [string]$websitePath, # this is a workaround to ensure if appSettings has no collection and we try to delete the only attribute, the entire node is not deleted. # if we try removing the only attribute even if there is one collection item, the node is preserved. I am not able to find a way to do this #using clear-webconfiguration alone. - Add-item -key "dummyKey" -value "dummyValue" -isAttribute $false -websitePath $websitePath -configSection $configSection + Add-item -key 'dummyKey' -value 'dummyValue' -isAttribute $false -websitePath $websitePath -configSection $configSection clear-WebConfiguration -filter $filter -PSPath $websitePath -WarningAction Stop - Remove-Item -key "dummyKey" -isAttribute $false -websitePath $websitePath -configSection $configSection + Remove-Item -key 'dummyKey' -isAttribute $false -websitePath $websitePath -configSection $configSection } } @@ -250,7 +250,7 @@ function Get-ItemValue([string]$key, [Boolean]$isAttribute, [string]$websitePath { $filter = "$defaultFilter/add[@key=`'$key`']" - $value = Get-WebConfigurationProperty -Filter $filter -Name "value" -PSPath $websitePath + $value = Get-WebConfigurationProperty -Filter $filter -Name 'value' -PSPath $websitePath } else diff --git a/DSCResources/MSFT_xWebSiteDefaults/MSFT_xWebSiteDefaults.psm1 b/DSCResources/MSFT_xWebSiteDefaults/MSFT_xWebSiteDefaults.psm1 new file mode 100644 index 000000000..1a064b95a --- /dev/null +++ b/DSCResources/MSFT_xWebSiteDefaults/MSFT_xWebSiteDefaults.psm1 @@ -0,0 +1,188 @@ +###################################################################################### +# DSC Resource for IIS Server level Web Site Defaults +# ApplicationHost.config: system.applicationHost/sites/siteDefaults +# +# only a limited number of settings are supported at this time +# We try to cover the most common use cases +# We have a single parameter for each setting +###################################################################################### +data LocalizedData +{ + # culture="en-US" + ConvertFrom-StringData @' +NoWebAdministrationModule=Please ensure that WebAdministration module is installed. +SettingValue=Changing default value '{0}' to '{1}' +ValueOk=Default value '{0}' is already '{1}' +'@ +} + +###################################################################################### +# The Get-TargetResource cmdlet. +# This function will get all supported site default values +###################################################################################### +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory)] + [ValidateSet('Machine')] + [string]$ApplyTo + ) + + # Check if WebAdministration module is present for IIS cmdlets + CheckIISPoshModule + + return @{LogFormat = (GetValue 'siteDefaults/logFile' 'logFormat') + TraceLogDirectory = ( GetValue 'siteDefaults/traceFailedRequestsLogging' 'directory') + DefaultApplicationPool = (GetValue 'applicationDefaults' 'applicationPool') + AllowSubDirConfig = (GetValue 'virtualDirectoryDefaults' 'allowSubDirConfig') + ApplyTo = 'Machine' + LogDirectory = (GetValue 'siteDefaults/logFile' 'directory')} +} + +###################################################################################### +# The Set-TargetResource cmdlet. +# This function will change a default setting if not already set +###################################################################################### +function Set-TargetResource +{ + param + ( + [ValidateSet('Machine')] + [parameter(Mandatory = $true)] + [string]$ApplyTo, + [ValidateSet('W3C','IIS','NCSA','Custom')] + [string]$LogFormat, + [string]$LogDirectory, + [string]$TraceLogDirectory, + [string]$DefaultApplicationPool, + [ValidateSet('true','false')] + [string]$AllowSubDirConfig + ) + + CheckIISPoshModule + + SetValue 'siteDefaults/logFile' 'logFormat' $LogFormat + SetValue 'siteDefaults/logFile' 'directory' $LogDirectory + SetValue 'siteDefaults/traceFailedRequestsLogging' 'directory' $TraceLogDirectory + SetValue 'applicationDefaults' 'applicationPool' $DefaultApplicationPool + SetValue 'virtualDirectoryDefaults' 'allowSubDirConfig' $AllowSubDirConfig +} + +###################################################################################### +# The Test-TargetResource cmdlet. +# This will test whether all given values are already set in the current configuration +###################################################################################### +function Test-TargetResource +{ + [OutputType([System.Boolean])] + param + ( + [ValidateSet('Machine')] + [parameter(Mandatory = $true)] + [string]$ApplyTo, + [ValidateSet('W3C','IIS','NCSA','Custom')] + [string]$LogFormat, + [string]$LogDirectory, + [string]$TraceLogDirectory, + [string]$DefaultApplicationPool, + [ValidateSet('true','false')] + [string]$AllowSubDirConfig + ) + + CheckIISPoshModule + + # check for the various given settings: + + if (!(CheckValue -path 'virtualDirectoryDefaults' -name 'allowSubDirConfig' -newValue $AllowSubDirConfig)) + { + return $false + } + + if (!(CheckValue -path 'siteDefaults/logFile' -name 'logFormat' -newValue $LogFormat)) + { + return $false + } + + if (!(CheckValue -path 'siteDefaults/logFile' -name 'directory' -newValue $LogDirectory)) + { + return $false + } + + if (!(CheckValue -path 'siteDefaults/traceFailedRequestsLogging' -name 'directory' -newValue $TraceLogDirectory)) + { + return $false + } + + if (!(CheckValue -path 'applicationDefaults' -name 'applicationPool' -newValue $DefaultApplicationPool)) + { + return $false + } + + # at this point all settings are ok and our desired state is met. + return $true +} + +###################################################################################### +# Helper Functions +###################################################################################### + +Function CheckValue([string]$path,[string]$name,[string]$newValue) +{ + if (!$newValue) + { + # if no new value was specified, we assume this value is okay. + return $true + } + + $existingValue = GetValue -Path $path -Name $name + if ($existingValue -ne $newValue) + { + return $false + } + else + { + $relPath = $path + '/' + $name + Write-Verbose($LocalizedData.ValueOk -f $relPath,$newValue); + return $true + } +} + +# some internal helper function to do the actual work: + +Function SetValue([string]$path,[string]$name,[string]$newValue) +{ + # if the variable doesn't exist, the user doesn't want to change this value + if (!$newValue) + { + return + } + + # get the existing value to compare + $existingValue = GetValue -Path $path -Name $name + if ($existingValue -ne $newValue) + { + Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.applicationHost/sites/$path" -name $name -value "$newValue" + $relPath = $path + '/' + $name + Write-Verbose($LocalizedData.SettingValue -f $relPath,$newValue); + } +} + +Function GetValue([string]$path,[string]$name) +{ + return Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.applicationHost/sites/$path" -name $name +} + +Function CheckIISPoshModule +{ + # Check if WebAdministration module is present for IIS cmdlets + if(!(Get-Module -ListAvailable -Name WebAdministration)) + { + Throw $LocalizedData.NoWebAdministrationModule + } +} + +# FUNCTIONS TO BE EXPORTED +Export-ModuleMember -function Get-TargetResource, Set-TargetResource, Test-TargetResource diff --git a/DSCResources/MSFT_xWebSiteDefaults/MSFT_xWebSiteDefaults.schema.mof b/DSCResources/MSFT_xWebSiteDefaults/MSFT_xWebSiteDefaults.schema.mof new file mode 100644 index 000000000..44b540490 --- /dev/null +++ b/DSCResources/MSFT_xWebSiteDefaults/MSFT_xWebSiteDefaults.schema.mof @@ -0,0 +1,10 @@ +[ClassVersion("1.0.0"), FriendlyName("xWebSiteDefaults")] +class MSFT_xWebSiteDefaults : OMI_BaseResource +{ + [Key, Description("Dummy value because we need a key, always 'Machine'"), ValueMap{"Machine"}, Values{"Machine"}] string ApplyTo; + [write, Description("sites/siteDefaults/logFile/logFormat"), ValueMap{"W3C","IIS","NCSA","Custom"}, Values{"W3C","IIS","NCSA","Custom"}] string LogFormat; + [write, Description("sites/siteDefaults/logFile/directory")] string LogDirectory; + [write, Description("sites/siteDefaults/traceFailedRequestsLogging/directory")] string TraceLogDirectory; + [write, Description("sites/applicationDefaults/applicationPool")] string DefaultApplicationPool; + [write, Description("sites/virtualDirectoryDefaults/allowSubDirConfig"), ValueMap{"true","false"}, Values{"true","false"}] string AllowSubDirConfig; +}; diff --git a/DSCResources/MSFT_xWebVirtualDirectory/MSFT_xWebVirtualDirectory.psm1 b/DSCResources/MSFT_xWebVirtualDirectory/MSFT_xWebVirtualDirectory.psm1 index 9a9d44f4b..7b821ae91 100644 --- a/DSCResources/MSFT_xWebVirtualDirectory/MSFT_xWebVirtualDirectory.psm1 +++ b/DSCResources/MSFT_xWebVirtualDirectory/MSFT_xWebVirtualDirectory.psm1 @@ -21,17 +21,17 @@ function Get-TargetResource $PhysicalPath ) - CheckDependencies + Test-Dependancies - $virtualDirectory = GetWebVirtualDirectoryInternal -Site $Website -Name $Name -Application $WebApplication + $virtualDirectory = Get-WebVirtualDirectoryInternal -Site $Website -Name $Name -Application $WebApplication - $PhysicalPath = "" - $Ensure = "Absent" + $PhysicalPath = '' + $Ensure = 'Absent' if ($virtualDirectory.Count -eq 1) { $PhysicalPath = $virtualDirectory.PhysicalPath - $Ensure = "Present" + $Ensure = 'Present' } $returnValue = @{ @@ -66,16 +66,16 @@ function Set-TargetResource [System.String] $PhysicalPath, - [ValidateSet("Present","Absent")] + [ValidateSet('Present','Absent')] [System.String] - $Ensure = "Present" + $Ensure = 'Present' ) - CheckDependencies + Test-Dependancies - if ($Ensure -eq "Present") + if ($Ensure -eq 'Present') { - $virtualDirectory = GetWebVirtualDirectoryInternal -Site $Website -Name $Name -Application $WebApplication + $virtualDirectory = Get-WebVirtualDirectoryInternal -Site $Website -Name $Name -Application $WebApplication if ($virtualDirectory.count -eq 0) { Write-Verbose "Creating new Web Virtual Directory $Name." @@ -88,7 +88,7 @@ function Set-TargetResource } } - if ($Ensure -eq "Absent") + if ($Ensure -eq 'Absent') { Write-Verbose "Removing existing Virtual Directory $Name." Remove-WebVirtualDirectory -Site $Website -Application $WebApplication -Name $Name @@ -117,21 +117,21 @@ function Test-TargetResource [System.String] $PhysicalPath, - [ValidateSet("Present","Absent")] + [ValidateSet('Present','Absent')] [System.String] - $Ensure = "Present" + $Ensure = 'Present' ) - CheckDependencies + Test-Dependancies - Write-Verbose "Checking the virtual directories for the website." - $virtualDirectory = GetWebVirtualDirectoryInternal -Site $Website -Name $Name -Application $WebApplication + Write-Verbose 'Checking the virtual directories for the website.' + $virtualDirectory = Get-WebVirtualDirectoryInternal -Site $Website -Name $Name -Application $WebApplication - if ($virtualDirectory.count -eq 1 -and $Ensure -eq "Present") + if ($virtualDirectory.Count -eq 1 -and $Ensure -eq 'Present') { - if ($virtualDirectory.physicalPath -eq $PhysicalPath) + if ($virtualDirectory.PhysicalPath -eq $PhysicalPath) { - Write-Verbose "Web virtual directory is in required state" + Write-Verbose 'Web virtual directory is in required state' return $true } else @@ -141,26 +141,26 @@ function Test-TargetResource } } - if ($virtualDirectory.count -eq 0 -and $Ensure -eq "Absent") + if ($virtualDirectory.count -eq 0 -and $Ensure -eq 'Absent') { - Write-Verbose "Web virtual direcotry $Name should be absent and is absent" + Write-Verbose "Web virtual directory $Name should be absent and is absent" return $true } return $false } -function CheckDependencies +function Test-Dependancies { - Write-Verbose "Checking whether WebAdministration is there in the machine or not." + Write-Verbose 'Checking whether WebAdministration is there in the machine or not.' # Check if WebAdministration module is present for IIS cmdlets if(!(Get-Module -ListAvailable -Name WebAdministration)) { - Throw "Please ensure that WebAdministration module is installed." + Throw 'Please ensure that WebAdministration module is installed.' } } -function GetWebVirtualDirectoryInternal +function Get-WebVirtualDirectoryInternal { param ( @@ -177,16 +177,15 @@ function GetWebVirtualDirectoryInternal $Application ) - If ((CheckApplicationExists -Site $Site -Application $Application) -ne $true) + if ((Test-ApplicationExists -Site $Site -Application $Application) -ne $true) { - $compositeVirtualDirectoryName = GetCompositeVirtualDirectoryName -Name $Name -Application $Application - return Get-WebVirtualDirectory -site $Site -Name $compositeVirtualDirectoryName + return Get-WebVirtualDirectory -Site $Site -Name $(Get-CompositeName -Name $Name -Application $Application) } - return Get-WebVirtualDirectory -site $Site -Application $Application -Name $Name + return Get-WebVirtualDirectory -Site $Site -Application $Application -Name $Name } -function CheckApplicationExists +function Test-ApplicationExists { param ( @@ -198,9 +197,10 @@ function CheckApplicationExists [System.String] $Application ) + $WebApplication = Get-WebApplication -Site $Site -Name $Application - if ($WebApplication.count -eq 1) + if ($WebApplication.Count -eq 1) { return $true } @@ -210,7 +210,7 @@ function CheckApplicationExists return $false } -function GetCompositeVirtualDirectoryName +function Get-CompositeName { param ( diff --git a/DSCResources/MSFT_xWebsite/MSFT_xWebsite.psm1 b/DSCResources/MSFT_xWebsite/MSFT_xWebsite.psm1 index 1a372dfab..d9fe4c13d 100644 --- a/DSCResources/MSFT_xWebsite/MSFT_xWebsite.psm1 +++ b/DSCResources/MSFT_xWebsite/MSFT_xWebsite.psm1 @@ -1,7 +1,8 @@ +#requires -Version 3 -Modules CimCmdlets data LocalizedData { # culture="en-US" - ConvertFrom-StringData @' + ConvertFrom-StringData -StringData @' SetTargetResourceInstallwhatIfMessage=Trying to create website "{0}". SetTargetResourceUnInstallwhatIfMessage=Trying to remove website "{0}". WebsiteNotFoundError=The requested website "{0}" is not found on the target machine. @@ -19,82 +20,93 @@ WebsiteBindingConflictOnStartError = Website "{0}" could not be started due to b } # The Get-TargetResource cmdlet is used to fetch the status of role or Website on the target machine. -# It gives the Website info of the requested role/feature on the target machine. -function Get-TargetResource +# It gives the Website info of the requested role/feature on the target machine. +function Get-TargetResource { [OutputType([System.Collections.Hashtable])] - param - ( + param + ( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] - [string]$Name + [string]$Name, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$PhysicalPath ) - $getTargetResourceResult = $null; + # Check if WebAdministration module is present for IIS cmdlets + if(!(Get-Module -ListAvailable -Name WebAdministration)) + { + Throw 'Please ensure that WebAdministration module is installed.' + } - # Check if WebAdministration module is present for IIS cmdlets - if(!(Get-Module -ListAvailable -Name WebAdministration)) - { - Throw "Please ensure that WebAdministration module is installed." - } + $Website = Get-Website | Where-Object -FilterScript { + $_.Name -eq $Name + } - $Website = Get-Website -Name $Name + if ($Website.count -eq 0) # No Website exists with this name. + { + $ensureResult = 'Absent' + } + elseif ($Website.count -eq 1) # A single Website exists with this name. + { + $ensureResult = 'Present' + + [PSObject[]] $Bindings + $Bindings = (Get-ItemProperty -Path IIS:\Sites\$Name -Name Bindings).collection - if ($Website.count -eq 0) # No Website exists with this name. + $CimBindings = foreach ($binding in $Bindings) { - $ensureResult = "Absent"; + $BindingObject = Get-WebBindingObject -BindingInfo $binding + New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ + Port = [System.UInt16]$BindingObject.Port + Protocol = $BindingObject.Protocol + IPAddress = $BindingObject.IPaddress + HostName = $BindingObject.Hostname + CertificateThumbprint = $BindingObject.CertificateThumbprint + CertificateStoreName = $BindingObject.CertificateStoreName + SSLFlags = $BindingObject.SSLFlags + } -ClientOnly } - elseif ($Website.count -eq 1) # A single Website exists with this name. - { - $ensureResult = "Present" - [PSObject[]] $Bindings - $Bindings = (get-itemProperty -path IIS:\Sites\$Name -Name Bindings).collection - - $CimBindings = foreach ($binding in $bindings) - { - $BindingObject = get-WebBindingObject -BindingInfo $binding - New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{Port=[System.UInt16]$BindingObject.Port;Protocol=$BindingObject.Protocol;IPAddress=$BindingObject.IPaddress;HostName=$BindingObject.Hostname;CertificateThumbprint=$BindingObject.CertificateThumbprint;CertificateStoreName=$BindingObject.CertificateStoreName} -ClientOnly - } - - $allDefaultPage = @(Get-WebConfiguration //defaultDocument/files/* -PSPath (Join-Path "IIS:\sites\" $Name) |%{Write-Output $_.value}) - - } - else # Multiple websites with the same name exist. This is not supported and is an error - { - $errorId = "WebsiteDiscoveryFailure"; - $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult - $errorMessage = $($LocalizedData.WebsiteUpdateFailureError) -f ${Name} - $exception = New-Object System.InvalidOperationException $errorMessage - $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null + $allDefaultPage = @(Get-WebConfiguration //defaultDocument/files/* -PSPath (Join-Path -Path 'IIS:\sites\' -ChildPath $Name) | ForEach-Object -Process { + Write-Output -InputObject $_.value + }) + } + else # Multiple websites with the same name exist. This is not supported and is an error + { + $errorId = 'WebsiteDiscoveryFailure' + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult + $errorMessage = $($LocalizedData.WebsiteDiscoveryFailureError) -f ${Name} + $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage + $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null - $PSCmdlet.ThrowTerminatingError($errorRecord); - } + $PSCmdlet.ThrowTerminatingError($errorRecord) + } - # Add all Website properties to the hash table - $getTargetResourceResult = @{ - Name = $Website.Name; - Ensure = $ensureResult; - PhysicalPath = $Website.physicalPath; - State = $Website.state; - ID = $Website.id; - ApplicationPool = $Website.applicationPool; - BindingInfo = $CimBindings; - DefaultPage = $allDefaultPage - } - - return $getTargetResourceResult; + # Add all Website properties to the hash table + return @{ + Name = $Website.Name + Ensure = $ensureResult + PhysicalPath = $Website.PhysicalPath + State = $Website.State + ID = $Website.ID + ApplicationPool = $Website.ApplicationPool + BindingInfo = $CimBindings + DefaultPage = $allDefaultPage + } } -# The Set-TargetResource cmdlet is used to create, delete or configuure a website on the target machine. -function Set-TargetResource +# The Set-TargetResource cmdlet is used to create, delete or configure a website on the target machine. +function Set-TargetResource { - [CmdletBinding(SupportsShouldProcess=$true)] - param - ( - [ValidateSet("Present", "Absent")] - [string]$Ensure = "Present", + [CmdletBinding(SupportsShouldProcess = $true)] + param + ( + [ValidateSet('Present', 'Absent')] + [string]$Ensure = 'Present', [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] @@ -104,262 +116,265 @@ function Set-TargetResource [ValidateNotNullOrEmpty()] [string]$PhysicalPath, - [ValidateSet("Started", "Stopped")] - [string]$State = "Started", + [ValidateSet('Started', 'Stopped')] + [string]$State = 'Started', [string]$ApplicationPool, [Microsoft.Management.Infrastructure.CimInstance[]]$BindingInfo, - [string[]]$DefaultPage + [string[]]$DefaultPage ) - - $getTargetResourceResult = $null; - if($Ensure -eq "Present") + $getTargetResourceResult = $null + + if($Ensure -eq 'Present') { #Remove Ensure from parameters as it is not needed to create new website - $Result = $psboundparameters.Remove("Ensure"); + $Result = $psboundparameters.Remove('Ensure') #Remove State parameter form website. Will start the website after configuration is complete - $Result = $psboundparameters.Remove("State"); + $Result = $psboundparameters.Remove('State') #Remove bindings from parameters if they exist #Bindings will be added to site using separate cmdlet - $Result = $psboundparameters.Remove("BindingInfo"); + $Result = $psboundparameters.Remove('BindingInfo') #Remove default pages from parameters if they exist #Default Pages will be added to site using separate cmdlet - $Result = $psboundparameters.Remove("DefaultPage"); + $Result = $psboundparameters.Remove('DefaultPage') # Check if WebAdministration module is present for IIS cmdlets if(!(Get-Module -ListAvailable -Name WebAdministration)) { - Throw "Please ensure that WebAdministration module is installed." + Throw 'Please ensure that WebAdministration module is installed.' + } + + $Website = Get-Website | Where-Object -FilterScript { + $_.Name -eq $Name } - $website = get-website $Name - if($website -ne $null) + if($Website -ne $null) { #update parameters as required $UpdateNotRequired = $true #Update Physical Path if required - if(ValidateWebsitePath -Name $Name -PhysicalPath $PhysicalPath) + if(Test-WebsitePath -Name $Name -PhysicalPath $PhysicalPath) { $UpdateNotRequired = $false - Set-ItemProperty "IIS:\Sites\$Name" -Name physicalPath -Value $PhysicalPath -ErrorAction Stop + Set-ItemProperty -Path "IIS:\Sites\$Name" -Name physicalPath -Value $PhysicalPath -ErrorAction Stop - Write-Verbose("Physical path for website $Name has been updated to $PhysicalPath"); + Write-Verbose -Message ("Physical path for website $Name has been updated to $PhysicalPath") } #Update Bindings if required if ($BindingInfo -ne $null) { - if(ValidateWebsiteBindings -Name $Name -BindingInfo $BindingInfo) + if(Test-WebsiteBindings -Name $Name -BindingInfo $BindingInfo) { $UpdateNotRequired = $false #Update Bindings - UpdateBindings -Name $Name -BindingInfo $BindingInfo -ErrorAction Stop + Update-WebsiteBinding -Name $Name -BindingInfo $BindingInfo -ErrorAction Stop - Write-Verbose("Bindings for website $Name have been updated."); + Write-Verbose -Message ("Bindings for website $Name have been updated.") } } #Update Application Pool if required - if(($website.applicationPool -ne $ApplicationPool) -and ($ApplicationPool -ne "")) + if(($Website.applicationPool -ne $ApplicationPool) -and ($ApplicationPool -ne '')) { $UpdateNotRequired = $false - Set-ItemProperty IIS:\Sites\$Name -Name applicationPool -Value $ApplicationPool -ErrorAction Stop + Set-ItemProperty -Path IIS:\Sites\$Name -Name applicationPool -Value $ApplicationPool -ErrorAction Stop - Write-Verbose("Application Pool for website $Name has been updated to $ApplicationPool") + Write-Verbose -Message ("Application Pool for website $Name has been updated to $ApplicationPool") } - #Update Default pages if required - if($DefaultPage -ne $null) + #Update Default pages if required + if($DefaultPage -ne $null) { - UpdateDefaultPages -Name $Name -DefaultPage $DefaultPage - } + Update-DefaultPages $Name -DefaultPage $DefaultPage + } #Update State if required - if($website.state -ne $State -and $State -ne "") + if($Website.state -ne $State -and $State -ne '') { $UpdateNotRequired = $false - if($State -eq "Started") + if($State -eq 'Started') { # Ensure that there are no other websites with binding information that will conflict with this site before starting - $existingSites = Get-Website | Where Name -ne $Name + $existingSites = Get-Website | Where-Object -Property Name -NE -Value $Name foreach($site in $existingSites) { - $siteInfo = Get-TargetResource -Name $site.name - + $siteInfo = Get-TargetResource -Name $site.Name -PhysicalPath $site.PhysicalPath + foreach ($binding in $BindingInfo) { #Normalize empty IPAddress to "*" - if($binding.IPAddress -eq "" -or $binding.IPAddress -eq $null) + if($binding.IPAddress -eq '' -or $binding.IPAddress -eq $null) { - $NormalizedIPAddress = "*" - } + $NormalizedIPAddress = '*' + } else { $NormalizedIPAddress = $binding.IPAddress } - if( !(EnsurePortIPHostUnique -Port $Binding.Port -IPAddress $NormalizedIPAddress -HostName $binding.HostName -BindingInfo $siteInfo.BindingInfo -UniqueInstances 1)) + if( !(Confirm-PortIPHostisUnique -Port $binding.Port -IPAddress $NormalizedIPAddress -HostName $binding.HostName -BindingInfo $siteInfo.BindingInfo -UniqueInstances 1)) { #return error & Do not start Website - $errorId = "WebsiteBindingConflictOnStart"; + $errorId = 'WebsiteBindingConflictOnStart' $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult - $errorMessage = $($LocalizedData.WebsiteBindingConflictOnStartError) -f ${Name} - $exception = New-Object System.InvalidOperationException $errorMessage - $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null + $errorMessage = $($LocalizedData.WebsiteBindingConflictOnStartError) -f ${Name} + $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage + $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null - $PSCmdlet.ThrowTerminatingError($errorRecord); - } + $PSCmdlet.ThrowTerminatingError($errorRecord) + } } } try { - - Start-Website -Name $Name - + Start-Website -Name $Name } catch { - $errorId = "WebsiteStateFailure"; - $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation; - $errorMessage = $($LocalizedData.WebsiteStateFailureError) -f ${Name} ; + $errorId = 'WebsiteStateFailure' + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation + $errorMessage = $($LocalizedData.WebsiteStateFailureError) -f ${Name} $errorMessage += $_.Exception.Message - $exception = New-Object System.InvalidOperationException $errorMessage ; - $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null + $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage + $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null - $PSCmdlet.ThrowTerminatingError($errorRecord); + $PSCmdlet.ThrowTerminatingError($errorRecord) } - } else { try { - - Stop-Website -Name $Name - + Stop-Website -Name $Name } catch { - $errorId = "WebsiteStateFailure"; - $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation; - $errorMessage = $($LocalizedData.WebsiteStateFailureError) -f ${Name} ; + $errorId = 'WebsiteStateFailure' + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation + $errorMessage = $($LocalizedData.WebsiteStateFailureError) -f ${Name} $errorMessage += $_.Exception.Message - $exception = New-Object System.InvalidOperationException $errorMessage ; - $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null + $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage + $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null $PSCmdlet.ThrowTerminatingError($errorRecord) } } - Write-Verbose("State for website $Name has been updated to $State"); - + Write-Verbose -Message ("State for website $Name has been updated to $State") } if($UpdateNotRequired) { - Write-Verbose("Website $Name already exists and properties do not need to be udpated."); + Write-Verbose -Message ("Website $Name already exists and properties do not need to be updated.") } - - } else #Website doesn't exist so create new one { try { - $Website = New-Website @psboundparameters + $Websites = Get-Website + if ($Websites -eq $null) + { + # We do not have any sites this will cause an exception in 2008R2 if we don't specify an ID + $Website = New-Website @psboundparameters -ID 1 + } + else + { + $Website = New-Website @psboundparameters + } $Result = Stop-Website $Website.name -ErrorAction Stop - + #Clear default bindings if new bindings defined and are different if($BindingInfo -ne $null) { - if(ValidateWebsiteBindings -Name $Name -BindingInfo $BindingInfo) + if(Test-WebsiteBindings -Name $Name -BindingInfo $BindingInfo) { - UpdateBindings -Name $Name -BindingInfo $BindingInfo + Update-WebsiteBinding -Name $Name -BindingInfo $BindingInfo } } - #Add Default pages for new created website - if($DefaultPage -ne $null) + #Add Default pages for new created website + if($DefaultPage -ne $null) { - UpdateDefaultPages -Name $Name -DefaultPage $DefaultPage - } + Update-DefaultPages -Name $Name -DefaultPage $DefaultPage + } + + Write-Verbose -Message ("successfully created website $Name") - Write-Verbose("successfully created website $Name") - #Start site if required - if($State -eq "Started") + if($State -eq 'Started') { #Wait 1 sec for bindings to take effect #I have found that starting the website results in an error if it happens to quickly - Start-Sleep -s 1 + Start-Sleep -Seconds 1 Start-Website -Name $Name -ErrorAction Stop } - Write-Verbose("successfully started website $Name") - + Write-Verbose -Message ("successfully started website $Name") } catch - { - $errorId = "WebsiteCreationFailure"; - $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation; - $errorMessage = $($LocalizedData.WebsiteCreationFailureError) -f ${Name} ; + { + $errorId = 'WebsiteCreationFailure' + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation + $errorMessage = $($LocalizedData.WebsiteCreationFailureError) -f ${Name} $errorMessage += $_.Exception.Message - $exception = New-Object System.InvalidOperationException $errorMessage ; - $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null - $PSCmdlet.ThrowTerminatingError($errorRecord); + $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage + $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null + $PSCmdlet.ThrowTerminatingError($errorRecord) } - } + } } - else #Ensure is set to "Absent" so remove website - { + else #Ensure is set to "Absent" so remove website + { try { - $website = get-website $Name - if($website -ne $null) + $Website = Get-Website | Where-Object -FilterScript { + $_.Name -eq $Name + } + if($Website -ne $null) { - Remove-website -name $Name - - Write-Verbose("Successfully removed Website $Name.") + Remove-Website -name $Name + Write-Verbose -Message ("Successfully removed Website $Name.") } else { - Write-Verbose("Website $Name does not exist.") + Write-Verbose -Message ("Website $Name does not exist.") } } catch { - $errorId = "WebsiteRemovalFailure"; - $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation; - $errorMessage = $($LocalizedData.WebsiteRemovalFailureError) -f ${Name} ; + $errorId = 'WebsiteRemovalFailure' + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation + $errorMessage = $($LocalizedData.WebsiteRemovalFailureError) -f ${Name} $errorMessage += $_.Exception.Message - $exception = New-Object System.InvalidOperationException $errorMessage ; - $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null + $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage + $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null - $PSCmdlet.ThrowTerminatingError($errorRecord); + $PSCmdlet.ThrowTerminatingError($errorRecord) } - } } # The Test-TargetResource cmdlet is used to validate if the role or feature is in a state as expected in the instance document. -function Test-TargetResource +function Test-TargetResource { [OutputType([System.Boolean])] - param - ( - [ValidateSet("Present", "Absent")] - [string]$Ensure = "Present", + param + ( + [ValidateSet('Present', 'Absent')] + [string]$Ensure = 'Present', [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] @@ -369,137 +384,117 @@ function Test-TargetResource [ValidateNotNullOrEmpty()] [string]$PhysicalPath, - [ValidateSet("Started", "Stopped")] - [string]$State = "Started", + [ValidateSet('Started', 'Stopped')] + [string]$State = 'Started', [string]$ApplicationPool, [Microsoft.Management.Infrastructure.CimInstance[]]$BindingInfo, - [string[]]$DefaultPage + [string[]]$DefaultPage ) - - $DesiredConfigurationMatch = $true; + + $DesiredConfigurationMatch = $true # Check if WebAdministration module is present for IIS cmdlets if(!(Get-Module -ListAvailable -Name WebAdministration)) { - Throw "Please ensure that WebAdministration module is installed." + Throw 'Please ensure that WebAdministration module is installed.' } - $website = Get-Website -Name $Name + $Website = Get-Website | Where-Object -FilterScript { + $_.Name -eq $Name + } $Stop = $true Do { #Check Ensure - if(($Ensure -eq "Present" -and $website -eq $null) -or ($Ensure -eq "Absent" -and $website -ne $null)) + if(($Ensure -eq 'Present' -and $Website -eq $null) -or ($Ensure -eq 'Absent' -and $Website -ne $null)) { $DesiredConfigurationMatch = $false - Write-Verbose("The Ensure state for website $Name does not match the desired state."); + Write-Verbose -Message ("The Ensure state for website $Name does not match the desired state.") break } # Only check properties if $website exists - if ($website -ne $null) + if ($Website -ne $null) { #Check Physical Path property - if(ValidateWebsitePath -Name $Name -PhysicalPath $PhysicalPath) + if(Test-WebsitePath -Name $Name -PhysicalPath $PhysicalPath) { $DesiredConfigurationMatch = $false - Write-Verbose("Physical Path of Website $Name does not match the desired state."); + Write-Verbose -Message ("Physical Path of Website $Name does not match the desired state.") break } #Check State - if($website.state -ne $State -and $State -ne $null) - { - $DesiredConfigurationMatch = $false - Write-Verbose("The state of Website $Name does not match the desired state."); - break - } + if($Website.state -ne $State -and $State -ne $null) + { + $DesiredConfigurationMatch = $false + Write-Verbose -Message ("The state of Website $Name does not match the desired state.") + break + } - #Check Application Pool property - if(($ApplicationPool -ne "") -and ($website.applicationPool -ne $ApplicationPool)) - { - $DesiredConfigurationMatch = $false - Write-Verbose("Application Pool for Website $Name does not match the desired state."); - break - } + #Check Application Pool property + if(($ApplicationPool -ne '') -and ($Website.applicationPool -ne $ApplicationPool)) + { + $DesiredConfigurationMatch = $false + Write-Verbose -Message ("Application Pool for Website $Name does not match the desired state.") + break + } #Check Binding properties if($BindingInfo -ne $null) { - if(ValidateWebsiteBindings -Name $Name -BindingInfo $BindingInfo) + if(Test-WebsiteBindings -Name $Name -BindingInfo $BindingInfo) { $DesiredConfigurationMatch = $false - Write-Verbose("Bindings for website $Name do not mach the desired state."); + Write-Verbose -Message ("Bindings for website $Name do not match the desired state.") break } - } } - #Check Default Pages - if($DefaultPage -ne $null) - { - $allDefaultPage = @(Get-WebConfiguration //defaultDocument/files/* -PSPath (Join-Path "IIS:\sites\" $Name) |%{Write-Output $_.value}) + #Check Default Pages + if($DefaultPage -ne $null) + { + $allDefaultPage = @(Get-WebConfiguration //defaultDocument/files/* -PSPath (Join-Path -Path 'IIS:\sites\' -ChildPath $Name) | ForEach-Object -Process { + Write-Output -InputObject $_.value + }) - $allDefaultPagesPresent = $true + $allDefaultPagesPresent = $true - foreach($page in $DefaultPage ) + foreach($page in $DefaultPage) + { + if(-not ($allDefaultPage -icontains $page)) { - if(-not ($allDefaultPage -icontains $page)) - { - $DesiredConfigurationMatch = $false - Write-Verbose("Default Page for website $Name do not mach the desired state."); - $allDefaultPagesPresent = $false - break - } + $DesiredConfigurationMatch = $false + Write-Verbose -Message ("Default Page for website $Name do not match the desired state.") + $allDefaultPagesPresent = $false + break } - - if($allDefaultPagesPresent -eq $false) - { - # This is to break out from Test - break - } } + if($allDefaultPagesPresent -eq $false) + { + # This is to break out from Test + break + } + } + $Stop = $false } - While($Stop) + While($Stop) - $DesiredConfigurationMatch; + $DesiredConfigurationMatch } #region HelperFunctions -# ValidateWebsite is a helper function used to validate the results -function ValidateWebsite -{ - param - ( - [object] $Website, - - [string] $Name - ) - - # If a wildCard pattern is not supported by the website provider. - # Hence we restrict user to request only one website information in a single request. - if($Website.Count-gt 1) - { - $errorId = "WebsiteDiscoveryFailure"; - $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult - $errorMessage = $($LocalizedData.WebsiteDiscoveryFailureError) -f ${Name} - $exception = New-Object System.InvalidOperationException $errorMessage - $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null - - $PSCmdlet.ThrowTerminatingError($errorRecord); - } -} # Helper function used to validate website path -function ValidateWebsitePath +function Test-WebsitePath { param ( @@ -508,72 +503,34 @@ function ValidateWebsitePath [string] $PhysicalPath ) - $PathNeedsUpdating = $false - - if((Get-ItemProperty "IIS:\Sites\$Name" -Name physicalPath) -ne $PhysicalPath) + if((Get-ItemProperty -Path "IIS:\Sites\$Name" -Name physicalPath) -ne $PhysicalPath) { - $PathNeedsUpdating = $true + return $true } - $PathNeedsUpdating - + return $false } # Helper function used to validate website bindings # Returns true if bindings are valid (ie. port, IPAddress & Hostname combinations are unique). -function ValidateWebsiteBindings -{ - Param - ( - [parameter()] - [string] - $Name, - - [parameter()] - [Microsoft.Management.Infrastructure.CimInstance[]] - $BindingInfo - ) - - - $Valid = $true - - foreach($binding in $BindingInfo) - { - # First ensure that desired binding information is valid ie. No duplicate IPAddres, Port, Host name combinations. - - if (!(EnsurePortIPHostUnique -Port $binding.Port -IPAddress $binding.IPAddress -HostName $Binding.Hostname -BindingInfo $BindingInfo) ) - { - $errorId = "WebsiteBindingInputInvalidation"; - $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult - $errorMessage = $($LocalizedData.WebsiteBindingInputInvalidationError) -f ${Name} - $exception = New-Object System.InvalidOperationException $errorMessage - $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null - - $PSCmdlet.ThrowTerminatingError($errorRecord); - } - } - - return compareWebsiteBindings -Name $Name -BindingInfo $BindingInfo -} - -function EnsurePortIPHostUnique +function Confirm-PortIPHostisUnique { param ( [parameter()] - [System.UInt16] + [System.UInt16] $Port, [parameter()] - [string] + [string] $IPAddress, [parameter()] - [string] + [string] $HostName, - [parameter(Mandatory=$true)] + [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [Microsoft.Management.Infrastructure.CimInstance[]] $BindingInfo, @@ -582,9 +539,9 @@ function EnsurePortIPHostUnique $UniqueInstances = 0 ) - foreach ($Binding in $BindingInfo) + foreach ($binding in $BindingInfo) { - if($binding.Port -eq $Port -and [string]$Binding.IPAddress -eq $IPAddress -and [string]$Binding.HostName -eq $HostName) + if($binding.Port -eq $Port -and [string]$binding.IPAddress -eq $IPAddress -and [string]$binding.HostName -eq $HostName) { $UniqueInstances += 1 } @@ -602,118 +559,153 @@ function EnsurePortIPHostUnique # Helper function used to compare website bindings of actual to desired # Returns true if bindings need to be updated and false if not. -function compareWebsiteBindings +function Test-WebsiteBindings { param ( [parameter()] - [string] + [string] $Name, - [parameter(Mandatory=$true)] + [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [Microsoft.Management.Infrastructure.CimInstance[]] $BindingInfo ) - #Assume bindingsNeedUpdating - $BindingNeedsUpdating = $false - #check to see if actual settings have been passed in. If not get them from website - if($ActualBindings -eq $null) + foreach($binding in $BindingInfo) { - $ActualBindings = Get-Website $Name | Get-WebBinding + # First ensure that desired binding information is valid ie. No duplicate IPAddres, Port, Host name combinations. - #Format Binding information: Split BindingInfo into individual Properties (IPAddress:Port:HostName) - $ActualBindingObjects = @() - foreach ($ActualBinding in $ActualBindings) + if (!(Confirm-PortIPHostisUnique -Port $binding.Port -IPAddress $binding.IPAddress -HostName $binding.Hostname -BindingInfo $BindingInfo) ) { - $ActualBindingObjects += get-WebBindingObject -BindingInfo $ActualBinding + $errorId = 'WebsiteBindingInputInvalidation' + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult + $errorMessage = $($LocalizedData.WebsiteBindingInputInvalidationError) -f ${Name} + $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage + $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null + + $PSCmdlet.ThrowTerminatingError($errorRecord) } } - + + # Assume bindings do not need updating + $BindingNeedsUpdating = $false + + <# + Currently there is a problem in the LCM where Get-WebBinding short circuts the verbose stream + Write-Log can be changed to add the -File switch to log to a directory for troubleshooting. + However it's pretty noisy so it's being left in but commented out. + #> + + $ActualBindings = Get-WebBinding -Name $Name + + # Format Binding information: Split BindingInfo into individual Properties (IPAddress:Port:HostName) + $ActualBindingObjects = @() + + foreach ($ActualBinding in $ActualBindings) + { + $ActualBindingObjects += Get-WebBindingObject -BindingInfo $ActualBinding + } + #Compare Actual Binding info ($FormatActualBindingInfo) to Desired($BindingInfo) try { if($BindingInfo.Count -le $ActualBindingObjects.Count) { - foreach($Binding in $BindingInfo) + foreach($binding in $BindingInfo) { - $ActualBinding = $ActualBindingObjects | ?{$_.Port -eq $Binding.CimInstanceProperties["Port"].Value} + $ActualBinding = $ActualBindingObjects | Where-Object -FilterScript { + $_.Port -eq $binding.CimInstanceProperties['Port'].Value + } if ($ActualBinding -ne $null) { - if([string]$ActualBinding.Protocol -ne [string]$Binding.CimInstanceProperties["Protocol"].Value) + if([string]$ActualBinding.Protocol -ne [string]$binding.CimInstanceProperties['Protocol'].Value) { + Write-Log "Protocol is Incorrect" -File $BindingNeedsUpdating = $true break } - if([string]$ActualBinding.IPAddress -ne [string]$Binding.CimInstanceProperties["IPAddress"].Value) + if([string]$ActualBinding.IPAddress -ne [string]$binding.CimInstanceProperties['IPAddress'].Value) { # Special case where blank IPAddress is saved as "*" in the binding information. - if([string]$ActualBinding.IPAddress -eq "*" -AND [string]$Binding.CimInstanceProperties["IPAddress"].Value -eq "") + if([string]$ActualBinding.IPAddress -eq '*' -AND [string]$binding.CimInstanceProperties['IPAddress'].Value -eq '') { #Do nothing } else { + Write-Log "IP Address Incorrect" -File $BindingNeedsUpdating = $true - break - } + break + } } - if([string]$ActualBinding.HostName -ne [string]$Binding.CimInstanceProperties["HostName"].Value) + if([string]$ActualBinding.HostName -ne [string]$binding.CimInstanceProperties['HostName'].Value) { + Write-Log "HostName is incorrect" -File $BindingNeedsUpdating = $true break } - if([string]$ActualBinding.CertificateThumbprint -ne [string]$Binding.CimInstanceProperties["CertificateThumbprint"].Value) + if([string]$ActualBinding.CertificateThumbprint -ne [string]$binding.CimInstanceProperties['CertificateThumbprint'].Value) { + Write-Log "CertificateThumbprint is incorrect" -File + Write-Log "Actual Binding: $($ActualBinding.CertificateThumbprint )" -File + Write-Log "Binding Value: $($binding.CimInstanceProperties['CertificateThumbprint'].Value)" -File $BindingNeedsUpdating = $true break } - if([string]$ActualBinding.CertificateStoreName -ne [string]$Binding.CimInstanceProperties["CertificateStoreName"].Value) + if(-not [string]::IsNullOrWhiteSpace([string]$ActualBinding.CertificateThumbprint) -and [string]$ActualBinding.CertificateStoreName -ne [string]$binding.CimInstanceProperties['CertificateStoreName'].Value) { + Write-Log "Thumbprint is incorrect" -File $BindingNeedsUpdating = $true break } - } - else - { + + if(-not [string]::IsNullOrWhiteSpace([string]$binding.CimInstanceProperties['SSLFlags'].Value) -and [string]$ActualBinding.SSLFlags -ne [string]$binding.CimInstanceProperties['SSLFlags'].Value) { + Write-Log "SSLFlags is incorrect" -File $BindingNeedsUpdating = $true break } } + else + { + Write-Log "No bindings returned" -File + $BindingNeedsUpdating = $true + break + } } } else { + Write-Log "Binding Count is incorrect" $BindingNeedsUpdating = $true } - $BindingNeedsUpdating - + return $BindingNeedsUpdating } catch { - $errorId = "WebsiteCompareFailure"; + $errorId = 'WebsiteCompareFailure' $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult - $errorMessage = $($LocalizedData.WebsiteCompareFailureError) -f ${Name} + $errorMessage = $($LocalizedData.WebsiteCompareFailureError) -f ${Name} $errorMessage += $_.Exception.Message - $exception = New-Object System.InvalidOperationException $errorMessage - $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null + $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage + $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null - $PSCmdlet.ThrowTerminatingError($errorRecord); + $PSCmdlet.ThrowTerminatingError($errorRecord) } } -function UpdateBindings +function Update-WebsiteBinding { param ( - [parameter(Mandatory=$true)] + [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $Name, @@ -722,135 +714,173 @@ function UpdateBindings [Microsoft.Management.Infrastructure.CimInstance[]] $BindingInfo ) - + #Need to clear the bindings before we can create new ones - Clear-ItemProperty IIS:\Sites\$Name -Name bindings -ErrorAction Stop + Clear-ItemProperty -Path IIS:\Sites\$Name -Name bindings -ErrorAction Stop foreach($binding in $BindingInfo) { - - $Protocol = $Binding.CimInstanceProperties["Protocol"].Value - $IPAddress = $Binding.CimInstanceProperties["IPAddress"].Value - $Port = $Binding.CimInstanceProperties["Port"].Value - $HostHeader = $Binding.CimInstanceProperties["HostName"].Value - $CertificateThumbprint = $Binding.CimInstanceProperties["CertificateThumbprint"].Value - $CertificateStoreName = $Binding.CimInstanceProperties["CertificateStoreName"].Value - + $Protocol = $binding.CimInstanceProperties['Protocol'].Value + $IPAddress = $binding.CimInstanceProperties['IPAddress'].Value + $Port = $binding.CimInstanceProperties['Port'].Value + $HostHeader = $binding.CimInstanceProperties['HostName'].Value + $CertificateThumbprint = $binding.CimInstanceProperties['CertificateThumbprint'].Value + $CertificateStoreName = $binding.CimInstanceProperties['CertificateStoreName'].Value + $SSLFlags = $binding.CimInstanceProperties['SSLFlags'].Value + $bindingParams = @{} $bindingParams.Add('-Name', $Name) $bindingParams.Add('-Port', $Port) - + #Set IP Address parameter if($IPAddress -ne $null) - { - $bindingParams.Add('-IPAddress', $IPAddress) - } + { + $bindingParams.Add('-IPAddress', $IPAddress) + } else # Default to any/all IP Addresses - { - $bindingParams.Add('-IPAddress', '*') - } + { + $bindingParams.Add('-IPAddress', '*') + } #Set protocol parameter - if($Protocol-ne $null) - { - $bindingParams.Add('-Protocol', $Protocol) - } + if($Protocol -ne $null) + { + $bindingParams.Add('-Protocol', $Protocol) + } else #Default to Http - { - $bindingParams.Add('-Protocol', 'http') - } + { + $bindingParams.Add('-Protocol', 'http') + } #Set Host parameter if it exists - if($HostHeader-ne $null){$bindingParams.Add('-HostHeader', $HostHeader)} + if($HostHeader -ne $null) + { + $bindingParams.Add('-HostHeader', $HostHeader) + } + + if(-not [string]::IsNullOrWhiteSpace($SSLFlags)) + { + $bindingParams.Add('-SSLFlags', $SSLFlags) + } try { New-WebBinding @bindingParams -ErrorAction Stop } - Catch + catch { - $errorId = "WebsiteBindingUpdateFailure"; + $errorId = 'WebsiteBindingUpdateFailure' $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult - $errorMessage = $($LocalizedData.WebsiteUpdateFailureError) -f ${Name} + $errorMessage = $($LocalizedData.WebsiteBindingUpdateFailureError) -f ${Name} $errorMessage += $_.Exception.Message - $exception = New-Object System.InvalidOperationException $errorMessage - $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null + $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage + $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null - $PSCmdlet.ThrowTerminatingError($errorRecord); + $PSCmdlet.ThrowTerminatingError($errorRecord) } try { - if($CertificateThumbprint -ne $null) + if ( -not [string]::IsNullOrWhiteSpace($CertificateThumbprint) ) { - $NewWebbinding = get-WebBinding -name $Name -Port $Port - $newwebbinding.AddSslCertificate($CertificateThumbprint, $CertificateStoreName) + $NewWebbinding = Get-WebBinding -Name $Name -Port $Port + $NewWebbinding.AddSslCertificate($CertificateThumbprint, $CertificateStoreName) } } catch { - $errorId = "WebBindingCertifcateError"; - $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation; - $errorMessage = $($LocalizedData.WebBindingCertifcateError) -f ${CertificateThumbprint} ; + $errorId = 'WebBindingCertifcateError' + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation + $errorMessage = $($LocalizedData.WebBindingCertifcateError) -f ${CertificateThumbprint} $errorMessage += $_.Exception.Message - $exception = New-Object System.InvalidOperationException $errorMessage ; - $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null + $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage + $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null - $PSCmdlet.ThrowTerminatingError($errorRecord); + $PSCmdlet.ThrowTerminatingError($errorRecord) } } - } -function get-WebBindingObject +function Get-WebBindingObject { - Param + param ( $BindingInfo ) #First split properties by ']:'. This will get IPv6 address split from port and host name - $Split = $BindingInfo.BindingInformation.split("[]") + $Split = $BindingInfo.BindingInformation.split('[]') if($Split.count -gt 1) { $IPAddress = $Split.item(1) - $Port = $split.item(2).split(":").item(1) - $HostName = $split.item(2).split(":").item(2) + $Port = $Split.item(2).split(':').item(1) + $HostName = $Split.item(2).split(':').item(2) } else { - $SplitProps = $BindingInfo.BindingInformation.split(":") + $SplitProps = $BindingInfo.BindingInformation.split(':') $IPAddress = $SplitProps.item(0) $Port = $SplitProps.item(1) $HostName = $SplitProps.item(2) } - - $WebBindingObject = New-Object PSObject -Property @{Protocol = $BindingInfo.protocol;IPAddress = $IPAddress;Port = $Port;HostName = $HostName;CertificateThumbprint = $BindingInfo.CertificateHash;CertificateStoreName = $BindingInfo.CertificateStoreName} - return $WebBindingObject + return New-Object -TypeName PSObject -Property @{ + Protocol = $BindingInfo.protocol + IPAddress = $IPAddress + Port = $Port + HostName = $HostName + CertificateThumbprint = $BindingInfo.CertificateHash + CertificateStoreName = $BindingInfo.CertificateStoreName + sslFlags = $BindingInfo.sslFlags + } } -# Helper function used to Update default pages of website -function UpdateDefaultPages +# Helper function used to Update default pages of website +function Update-DefaultPages { param - ( + ( [string] $Name, [string[]] $DefaultPage ) - $allDefaultPage = @(Get-WebConfiguration //defaultDocument/files/* -PSPath (Join-Path "IIS:\sites\" $Name) |%{Write-Output $_.value}) + $allDefaultPage = @(Get-WebConfiguration //defaultDocument/files/* -PSPath (Join-Path -Path 'IIS:\sites\' -ChildPath $Name) | ForEach-Object -Process { + Write-Output -InputObject $_.value + }) - foreach($page in $DefaultPage ) + foreach($page in $DefaultPage) + { + if(-not ($allDefaultPage -icontains $page)) { - if(-not ($allDefaultPage -icontains $page)) - { - Write-Verbose("Deafult page for website $Name has been updated to $page"); - Add-WebConfiguration //defaultDocument/files -PSPath (Join-Path "IIS:\sites\" $Name) -Value @{value = $page } + Write-Verbose -Message ("Deafult page for website $Name has been updated to $page") + Add-WebConfiguration //defaultDocument/files -PSPath (Join-Path -Path 'IIS:\sites\' -ChildPath $Name) -Value @{ + value = $page } } + } } -#endregion +function Write-Log +{ + param + ( + [parameter(Position=1)] + [string] + $Message, + + [switch] $File + ) + + $filename = "$env:tmp\xWebSite.log" + Write-Verbose -Verbose -Message $message + + if ($File) + { + $date = Get-Date + "${date}: $message" | Out-File -Append -FilePath $filename + } +} + +#endregion diff --git a/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof b/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof index 02e80023b..a16ea77ec 100644 --- a/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof +++ b/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof @@ -1,4 +1,4 @@ -[ClassVersion("1.0.0")] +[ClassVersion("1.0.0")] Class MSFT_xWebBindingInformation { [write]UInt16 Port; @@ -6,21 +6,22 @@ Class MSFT_xWebBindingInformation [write]String IPAddress; [write]String HostName; [write]String CertificateThumbprint; - [write,ValueMap{"Personal", "WebHosting"},Values{"Personal", "WebHosting"}] string CertificateStoreName; + [write,ValueMap{"My", "WebHosting"},Values{"My", "WebHosting"}] string CertificateStoreName; + [write,ValueMap{"0","1","2","3"},Values{"0","1","2","3"}] string SSLFlags; }; -[ClassVersion("2.0.0"), FriendlyName("xWebsite")] +[ClassVersion("2.0.0"), FriendlyName("xWebsite")] class MSFT_xWebsite : OMI_BaseResource { [Key] string Name; - [write] string PhysicalPath; + [Required] string PhysicalPath; [write,ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] string Ensure; [write,ValueMap{"Started","Stopped"},Values{"Started", "Stopped"}] string State; [write, EmbeddedInstance("MSFT_xWebBindingInformation"), Description("Hashtable containing binding information (Port, Protocol, IPAddress, HostName, CertificateThumbPrint, CertificateStore)")] string BindingInfo[]; [write] string ApplicationPool; [read] string Id; [write, Description("The default pages for the website")] String DefaultPage[]; -}; +}; diff --git a/Examples/Sample_xIisFeatureDelegation_AllowSome.ps1 b/Examples/Sample_xIisFeatureDelegation_AllowSome.ps1 new file mode 100644 index 000000000..31d462c24 --- /dev/null +++ b/Examples/Sample_xIisFeatureDelegation_AllowSome.ps1 @@ -0,0 +1,39 @@ +configuration Sample_IISFeatureDelegation +{ + param + ( + # Target nodes to apply the configuration + [string[]]$NodeName = 'localhost' + ) + + # Import the module that defines custom resources + Import-DscResource -Module xWebAdministration, PSDesiredStateConfiguration + + Node $NodeName + { + # Install the IIS role + WindowsFeature IIS + { + Ensure = 'Present' + Name = 'Web-Server' + } + + # Allow Write access to some section that normally don't have it. + xIisFeatureDelegation serverRuntime + { + SectionName = 'serverRuntime' + OverrideMode = 'Allow' + } + xIisFeatureDelegation anonymousAuthentication + { + SectionName = 'security/authentication/anonymousAuthentication' + OverrideMode = 'Allow' + } + + xIisFeatureDelegation ipSecurity + { + SectionName = 'security/ipSecurity' + OverrideMode = 'Allow' + } + } +} diff --git a/Examples/Sample_xIisHandler_Remove32Bit.ps1 b/Examples/Sample_xIisHandler_Remove32Bit.ps1 new file mode 100644 index 000000000..eadfde450 --- /dev/null +++ b/Examples/Sample_xIisHandler_Remove32Bit.ps1 @@ -0,0 +1,52 @@ +configuration Sample_RemoveSome32BitHandlers +{ + param + ( + # Target nodes to apply the configuration + [string[]]$NodeName = 'localhost' + ) + + # Import the module that defines custom resources + Import-DscResource -Module xWebAdministration, PSDesiredStateConfiguration + + Node $NodeName + { + # Install the IIS role + WindowsFeature IIS + { + Ensure = 'Present' + Name = 'Web-Server' + } + + xIisHandler aspq_ISAPI_4_0_32bit + { + Name = 'aspq-ISAPI-4.0_32bit' + Ensure = 'Absent' + } + + xIisHandler cshtm_ISAPI_4_0_32bit + { + Name = 'cshtm-ISAPI-4.0_32bit' + Ensure = 'Absent' + } + + xIisHandler cshtml_ISAPI_4_0_32bit + { + Name = 'cshtml-ISAPI-4.0_32bit' + Ensure = 'Absent' + } + + xIisHandler vbhtm_ISAPI_4_0_32bit + { + Name = 'vbhtm-ISAPI-4.0_32bit' + Ensure = 'Absent' + } + + xIisHandler vbhtml_ISAPI_4_0_32bit + { + Name = 'vbhtml-ISAPI-4.0_32bit' + Ensure = 'Absent' + } + + } +} diff --git a/Examples/Sample_xIisMimeTypeMapping_RemoveVideo.ps1 b/Examples/Sample_xIisMimeTypeMapping_RemoveVideo.ps1 new file mode 100644 index 000000000..3addb9884 --- /dev/null +++ b/Examples/Sample_xIisMimeTypeMapping_RemoveVideo.ps1 @@ -0,0 +1,55 @@ +configuration Sample_RemoveVideoMimeTypeMappings +{ + param + ( + # Target nodes to apply the configuration + [string[]]$NodeName = 'localhost' + ) + + # Import the module that defines custom resources + Import-DscResource -Module xWebAdministration, PSDesiredStateConfiguration + + Node $NodeName + { + # Install the IIS role + WindowsFeature IIS + { + Ensure = 'Present' + Name = 'Web-Server' + } + + # Remove a bunch of Video Mime Type mappings + xIisMimeTypeMapping Mp2 + { + Ensure = 'Absent' + Extension = '.mp2' + MimeType = 'video/mpeg' + DependsOn = '[WindowsFeature]IIS' + } + + xIisMimeTypeMapping Mp4 + { + Ensure = 'Absent' + Extension = '.mp4' + MimeType = 'video/mp4' + DependsOn = '[WindowsFeature]IIS' + } + + xIisMimeTypeMapping Mpeg + { + Ensure = 'Absent' + Extension = '.mpeg' + MimeType = 'video/mpeg' + DependsOn = '[WindowsFeature]IIS' + } + + # we only allow the mpg Video extension on our server + xIisMimeTypeMapping Mpg + { + Ensure = 'Present' + Extension = '.mpg' + MimeType = 'video/mpeg' + DependsOn = '[WindowsFeature]IIS' + } + } +} diff --git a/Examples/Sample_xIisServerDefaults.ps1 b/Examples/Sample_xIisServerDefaults.ps1 new file mode 100644 index 000000000..385f3a773 --- /dev/null +++ b/Examples/Sample_xIisServerDefaults.ps1 @@ -0,0 +1,29 @@ +configuration Sample_IISServerDefaults +{ + param + ( + # Target nodes to apply the configuration + [string[]]$NodeName = 'localhost' + ) + + # Import the module that defines custom resources + Import-DscResource -Module xWebAdministration, PSDesiredStateConfiguration + + Node $NodeName + { + xWebSiteDefaults SiteDefaults + { + ApplyTo = 'Machine' + LogFormat = 'IIS' + AllowSubDirConfig = 'true' + } + + + xWebAppPoolDefaults PoolDefaults + { + ApplyTo = 'Machine' + ManagedRuntimeVersion = 'v4.0' + IdentityType = 'ApplicationPoolIdentity' + } + } +} diff --git a/Examples/Sample_xWebsite_ConfigurationData.psd1 b/Examples/Sample_xWebsite_ConfigurationData.psd1 index 65cb41197..bef6699fe 100644 --- a/Examples/Sample_xWebsite_ConfigurationData.psd1 +++ b/Examples/Sample_xWebsite_ConfigurationData.psd1 @@ -5,21 +5,21 @@ # All the WebServer has following identical information @{ - NodeName = "*" - WebsiteName = "FourthCoffee" - SourcePath = "C:\BakeryWebsite\" - DestinationPath = "C:\inetpub\FourthCoffee" - DefaultWebSitePath = "C:\inetpub\wwwroot" + NodeName = '*' + WebsiteName = 'FourthCoffee' + SourcePath = 'C:\BakeryWebsite\' + DestinationPath = 'C:\inetpub\FourthCoffee' + DefaultWebSitePath = 'C:\inetpub\wwwroot' }, @{ - NodeName = "WebServer1.fourthcoffee.com" - Role = "Web" + NodeName = 'WebServer1.fourthcoffee.com' + Role = 'Web' }, @{ - NodeName = "WebServer2.fourthcoffee.com" - Role = "Web" + NodeName = 'WebServer2.fourthcoffee.com' + Role = 'Web' } ); } diff --git a/Examples/Sample_xWebsite_NewWebsite.ps1 b/Examples/Sample_xWebsite_NewWebsite.ps1 index d1604b498..63bc211ff 100644 --- a/Examples/Sample_xWebsite_NewWebsite.ps1 +++ b/Examples/Sample_xWebsite_NewWebsite.ps1 @@ -27,43 +27,43 @@ configuration Sample_xWebsite_NewWebsite ) # Import the module that defines custom resources - Import-DscResource -Module xWebAdministration + Import-DscResource -Module xWebAdministration, PSDesiredStateConfiguration Node $NodeName { # Install the IIS role WindowsFeature IIS { - Ensure = "Present" - Name = "Web-Server" + Ensure = 'Present' + Name = 'Web-Server' } # Install the ASP .NET 4.5 role WindowsFeature AspNet45 { - Ensure = "Present" - Name = "Web-Asp-Net45" + Ensure = 'Present' + Name = 'Web-Asp-Net45' } # Stop the default website xWebsite DefaultSite { - Ensure = "Present" - Name = "Default Web Site" - State = "Stopped" - PhysicalPath = "C:\inetpub\wwwroot" - DependsOn = "[WindowsFeature]IIS" + Ensure = 'Present' + Name = 'Default Web Site' + State = 'Stopped' + PhysicalPath = 'C:\inetpub\wwwroot' + DependsOn = '[WindowsFeature]IIS' } # Copy the website content File WebContent { - Ensure = "Present" + Ensure = 'Present' SourcePath = $SourcePath DestinationPath = $DestinationPath Recurse = $true - Type = "Directory" - DependsOn = "[WindowsFeature]AspNet45" + Type = 'Directory' + DependsOn = '[WindowsFeature]AspNet45' } # Create the new AppPool @@ -82,11 +82,11 @@ configuration Sample_xWebsite_NewWebsite # Create the new Website xWebsite NewWebsite { - Ensure = "Present" + Ensure = 'Present' Name = $WebSiteName - State = "Started" + State = 'Started' PhysicalPath = $DestinationPath - DependsOn = "[File]WebContent" + DependsOn = '[File]WebContent' } } } diff --git a/Examples/Sample_xWebsite_NewWebsiteFromConfigurationData.ps1 b/Examples/Sample_xWebsite_NewWebsiteFromConfigurationData.ps1 index db45ee14f..da0f73a45 100644 --- a/Examples/Sample_xWebsite_NewWebsiteFromConfigurationData.ps1 +++ b/Examples/Sample_xWebsite_NewWebsiteFromConfigurationData.ps1 @@ -1,54 +1,54 @@ Configuration Sample_xWebsite_FromConfigurationData { # Import the module that defines custom resources - Import-DscResource -Module xWebAdministration + Import-DscResource -Module xWebAdministration, PSDesiredStateConfiguration # Dynamically find the applicable nodes from configuration data - Node $AllNodes.where{$_.Role -eq "Web"}.NodeName + Node $AllNodes.where{$_.Role -eq 'Web'}.NodeName { # Install the IIS role WindowsFeature IIS { - Ensure = "Present" - Name = "Web-Server" + Ensure = 'Present' + Name = 'Web-Server' } # Install the ASP .NET 4.5 role WindowsFeature AspNet45 { - Ensure = "Present" - Name = "Web-Asp-Net45" + Ensure = 'Present' + Name = 'Web-Asp-Net45' } # Stop an existing website (set up in Sample_xWebsite_Default) xWebsite DefaultSite { - Ensure = "Present" - Name = "Default Web Site" - State = "Stopped" + Ensure = 'Present' + Name = 'Default Web Site' + State = 'Stopped' PhysicalPath = $Node.DefaultWebSitePath - DependsOn = "[WindowsFeature]IIS" + DependsOn = '[WindowsFeature]IIS' } # Copy the website content File WebContent { - Ensure = "Present" + Ensure = 'Present' SourcePath = $Node.SourcePath DestinationPath = $Node.DestinationPath Recurse = $true - Type = "Directory" - DependsOn = "[WindowsFeature]AspNet45" + Type = 'Directory' + DependsOn = '[WindowsFeature]AspNet45' } # Create a new website xWebsite BakeryWebSite { - Ensure = "Present" + Ensure = 'Present' Name = $Node.WebsiteName - State = "Started" + State = 'Started' PhysicalPath = $Node.DestinationPath - DependsOn = "[File]WebContent" + DependsOn = '[File]WebContent' } } } diff --git a/Examples/Sample_xWebsite_RemoveDefault.ps1 b/Examples/Sample_xWebsite_RemoveDefault.ps1 index dc5aba6a3..0929f1143 100644 --- a/Examples/Sample_xWebsite_RemoveDefault.ps1 +++ b/Examples/Sample_xWebsite_RemoveDefault.ps1 @@ -7,25 +7,25 @@ configuration Sample_xWebsite_StopDefault ) # Import the module that defines custom resources - Import-DscResource -Module xWebAdministration + Import-DscResource -Module xWebAdministration, PSDesiredStateConfiguration Node $NodeName { # Install the IIS role WindowsFeature IIS { - Ensure = "Present" - Name = "Web-Server" + Ensure = 'Present' + Name = 'Web-Server' } # Stop the default website xWebsite DefaultSite { - Ensure = "Present" - Name = "Default Web Site" - State = "Stopped" - PhysicalPath = "C:\inetpub\wwwroot" - DependsOn = "[WindowsFeature]IIS" + Ensure = 'Present' + Name = 'Default Web Site' + State = 'Stopped' + PhysicalPath = 'C:\inetpub\wwwroot' + DependsOn = '[WindowsFeature]IIS' } } } diff --git a/Examples/Sample_xWebsite_WithSSLFlags.ps1 b/Examples/Sample_xWebsite_WithSSLFlags.ps1 new file mode 100644 index 000000000..bad402e86 --- /dev/null +++ b/Examples/Sample_xWebsite_WithSSLFlags.ps1 @@ -0,0 +1,86 @@ +configuration Sample_xWebsite_NewWebsite +{ + param + ( + # Target nodes to apply the configuration + [string[]]$NodeName = 'localhost', + + # Name of the website to create + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$WebSiteName, + + # Source Path for Website content + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$SourcePath, + + # Destination path for Website content + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$DestinationPath + ) + + # Import the module that defines custom resources + Import-DscResource -Module xWebAdministration + + Node $NodeName + { + # Install the IIS role + WindowsFeature IIS + { + Ensure = "Present" + Name = "Web-Server" + } + + # Install the ASP .NET 4.5 role + WindowsFeature AspNet45 + { + Ensure = "Present" + Name = "Web-Asp-Net45" + } + + # Stop the default website + xWebsite DefaultSite + { + Ensure = "Present" + Name = "Default Web Site" + State = "Stopped" + PhysicalPath = "C:\inetpub\wwwroot" + DependsOn = "[WindowsFeature]IIS" + } + + # Copy the website content + File WebContent + { + Ensure = "Present" + SourcePath = $SourcePath + DestinationPath = $DestinationPath + Recurse = $true + Type = "Directory" + DependsOn = "[WindowsFeature]AspNet45" + } + + # Create the new Website + # Have it set to the CertificateThumbprint + # and set that the Server Name Indication is required + xWebsite NewWebsite + { + Ensure = "Present" + Name = $WebSiteName + State = "Started" + PhysicalPath = $DestinationPath + DependsOn = "[File]WebContent" + BindingInfo = MSFT_cWebBindingInformation + { + Protocol = 'https' + Port = '443' + CertificateStoreName = 'MY' + CertificateThumbprint = 'BB84DE3EC423DDDE90C08AB3C5A828692089493C' + HostName = $Website + IPAddress = '*' + SSLFlags = '1' + } + } + } +} diff --git a/README.md b/README.md index c44a9cb72..db107cc4d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,576 @@ -[![Build status](https://ci.appveyor.com/api/projects/status/gnsxkjxht31ctan1/branch/master?svg=true)](https://ci.appveyor.com/project/PowerShell/xwebadministration/branch/master) +[![Build status](https://ci.appveyor.com/api/projects/status/gnsxkjxht31ctan1/branch/master?svg=true)](https://ci.appveyor.com/project/PowerShell/xwebadministration/branch/master) # xWebAdministration -{{Description}} +The **xWebAdministration** module contains the **xIisModule**, **xWebAppPool**, **xWebsite**, **xWebApplication**, **xWebVirtualDirectory**, and **xWebConfigKeyValue** DSC resources for creating and configuring various IIS artifacts. ## Contributing Please check out common DSC Resources [contributing guidelines](https://github.com/PowerShell/DscResource.Kit/blob/master/CONTRIBUTING.md). + + +## Resources + +### xIISModule + +* **Path**: The path to the module to be registered. +* **Name**: The logical name to register the module as in IIS. +* **RequestPath**: The allowed request paths, such as *.php +* **Verb**: An array of allowed verbs, such as get and post. +* **SiteName**: The name of the Site to register the module for. +If empty, the resource will register the module with all of IIS. +* **ModuleType**: The type of the module. +Currently, only FastCgiModule is supported. +* **Ensure**: Ensures that the module is **Present** or **Absent**. + +### xWebAppPool + +* **Name**: The desired name of the web application pool +* **Ensure**: Should the application pool be present or absent +* **State**: State of the application pool – started or stopped + +### xWebsite + +* **Name**: The desired name of the website. +* **PhysicalPath**: The path to the files that compose the website. +* **State**: State of the website: { Started | Stopped } +* **BindingInfo**: Website's binding information. +* **ApplicationPool**: The website’s application pool. +* **Ensure**: Ensures that the website is **Present** or **Absent**. + +### xWebApplication + +* **Website**: Name of website with which the web application is associated. +* **Name**: The desired name of the web application. +* **WebAppPool**: Web application’s application pool. +* **PhysicalPath**: The path to the files that compose the web application. +* **Ensure**: Ensures that the web application is **Present** or **Absent**. + +### xWebVirtualDirectory + +* **Website**: Name of website with which virtual directory is associated +* **WebApplication**: Web application name for the virtual directory +* **PhysicalPath**: The path to the files that compose the virtual directory +* **Name**: The name of the virtual directory +* **Ensure**: Ensures if the virtual directory is Present or Absent. +* **State**: State of the application pool: { **Started** | **Stopped** } + +### xWebConfigKeyValue + +* **WebsitePath**: Path to website location (IIS or WebAdministration format). +* **ConfigSection**: Section to update (only AppSettings supported as of now). +* **KeyValuePair**: Key value pair for AppSettings (ItemCollection format). + + +## Versions + +### Unreleased +* Modified xWebsite to allow Server Name Indication when specifiying SSL certificates. +* Change Test Get-Website to match other function +* Removed xDscResourceDesigner tests +* Suppress extra verbose messages when -verbose is specified to Start-DscConfiguration +* Moved tests into child folders Unit and Integration +* Added PSDesiredStateConfiguration to Import-DscResource statement +* Fixed issue where Set-TargetResource was being run unexpectedly +* Added Tests to MSFT_xWebVirtualDirectory +* xWebsite tests updates +* xWebVirtualDirectory tests updates + +### 1.7.0.0 + +* Added following resources: + * xIisHandler + * xIisFeatureDelegation + * xIisMimeTypeMapping + * xWebAppPoolDefaults + * xWebSiteDefaults +* Modified xWebsite schema to make PhysicalPath required + +### 1.6.0.0 + +* Fixed bug in xWebsite resource regarding incorrect name of personal certificate store. + +### 1.5.0.0 + +* xWebsite: + - Fix issue with Get-Website when there are multiple sites. + - Fix issue when trying to add a new website when no websites currently exist. + - Fix typos. + +### 1.4.0.0 + +Changed Key property in MSFT_xWebConfigKeyValue to be a Key, instead of Required. This allows multiple keys to be configured within the same web.config file. + +### 1.3.2.4 + +* Fixed the confusion with mismatched versions and xWebDeploy resources +* Removed BakeryWebsite.zip for legal reasons. Please read Examples\README.md for the workaround. + +### 1.3.2.3 + +* Fixed variable name typo in MSFT_xIisModule. +* Added OutputType attribute to Test-TargetResource and Get-TargetResource in MSFT_xWebSite. + +### 1.3.2.2 + +* Documentation only change. +Module manifest metadata changed to improve PowerShell Gallery experience. + +### 1.3.2.1 + +* Documentation-only change, added metadata to module manifest + +### 1.3.2 + +* Added **xIisModule** + +### 1.2 + +* Added the **xWebAppPool**, **xWebApplication**, **xWebVirtualDirectory**, and **xWebConfigKeyValue**. + +### 1.1.0.0 + +* Added support for HTTPS protocol +* Updated binding information to include Certificate information for HTTPS +* Removed protocol property. Protocol is included in binding information +* Bug fixes + +### 1.0.0.0 + +* Initial release with the following resources + - **xWebsite** + + +## Examples + +### Registering PHP + +When configuring an IIS Application that uses PHP, you first need to register the PHP CGI module with IIS. +The following **xPhp** configuration downloads and installs the prerequisites for PHP, downloads PHP, registers the PHP CGI module with IIS and sets the system environment variable that PHP needs to run. + +Note: This example is intended to be used as a composite resource, so it does not use Configuration Data. +Please see the [Composite Configuration Blog](http://blogs.msdn.com/b/powershell/archive/2014/02/25/reusing-existing-configuration-scripts-in-powershell-desired-state-configuration.aspx) on how to use this configuration in another configuration. + +```powershell +# Composite configuration to install the IIS pre-requisites for PHP +Configuration IisPreReqs_php +{ +param + ( + [Parameter(Mandatory = $true)] + [Validateset("Present","Absent")] + [String] + $Ensure + ) + foreach ($Feature in @("Web-Server","Web-Mgmt-Tools","web-Default-Doc", ` +"Web-Dir-Browsing","Web-Http-Errors","Web-Static-Content",` + "Web-Http-Logging","web-Stat-Compression","web-Filtering",` + "web-CGI","web-ISAPI-Ext","web-ISAPI-Filter")) + { + WindowsFeature "$Feature$Number" + { + Ensure = $Ensure + Name = $Feature + } + } +} +# Composite configuration to install PHP on IIS +configuration xPhp +{ + param( + [Parameter(Mandatory = $true)] + [switch] $installMySqlExt, + [Parameter(Mandatory = $true)] + [string] $PackageFolder, + [Parameter(Mandatory = $true)] + [string] $DownloadUri, + [Parameter(Mandatory = $true)] + [string] $Vc2012RedistDownloadUri, + [Parameter(Mandatory = $true)] + [String] $DestinationPath, + [Parameter(Mandatory = $true)] + [string] $ConfigurationPath + ) + # Make sure the IIS Prerequisites for PHP are present + IisPreReqs_php Iis + { + Ensure = "Present" + # Removed because this dependency does not work in + # Windows Server 2012 R2 and below + # This should work in WMF v5 and above + # DependsOn = "[File]PackagesFolder" + } + # Download and install Visual C Redist2012 from chocolatey.org + Package vcRedist + { + Path = $Vc2012RedistDownloadUri + ProductId = "{CF2BEA3C-26EA-32F8-AA9B-331F7E34BA97}" + Name = "Microsoft Visual C++ 2012 x64 Minimum Runtime - 11.0.61030" + Arguments = "/install /passive /norestart" + } + $phpZip = Join-Path $PackageFolder "php.zip" + # Make sure the PHP archine is in the package folder + xRemoteFile phpArchive + { + uri = $DownloadURI + DestinationPath = $phpZip + } + # Make sure the content of the PHP archine are in the PHP path + Archive php + { + Path = $phpZip + Destination = $DestinationPath + } + if ($installMySqlExt ) + { + # Make sure the MySql extention for PHP is in the main PHP path + File phpMySqlExt + { + SourcePath = "$($DestinationPath)\ext\php_mysql.dll" + DestinationPath = "$($DestinationPath)\php_mysql.dll" + Ensure = "Present" + DependsOn = @("[Archive]PHP") + MatchSource = $true + } + } + + # Make sure the php.ini is in the Php folder + File PhpIni + { + SourcePath = $ConfigurationPath + DestinationPath = "$($DestinationPath)\php.ini" + DependsOn = @("[Archive]PHP") + MatchSource = $true + } + # Make sure the php cgi module is registered with IIS + xIisModule phpHandler + { + Name = "phpFastCgi" + Path = "$($DestinationPath)\php-cgi.exe" + RequestPath = "*.php" + Verb = "*" + Ensure = "Present" + DependsOn = @("[Package]vcRedist","[File]PhpIni") + # Removed because this dependency does not work in + # Windows Server 2012 R2 and below + # This should work in WMF v5 and above + # "[IisPreReqs_php]Iis" + } + # Make sure the php binary folder is in the path + Environment PathPhp + { + Name = "Path" + Value = ";$($DestinationPath)" + Ensure = "Present" + Path = $true + DependsOn = "[Archive]PHP" + } +} +xPhp -PackageFolder "C:\packages" ` + -DownloadUri -DownloadUri "http://windows.php.net/downloads/releases/php-5.5.13-Win32-VC11-x64.zip" ` + -Vc2012RedistDownloadUri "http://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe" ` + -DestinationPath "C:\php" ` + -ConfigurationPath "C:\MyPhp.ini" ` + -installMySqlExt $false +``` + +## Stopping the default website + +When configuring a new IIS server, several references recommend removing or stopping the default website for security purposes. +This example sets up your IIS web server by installing IIS Windows Feature. +After that, it will stop the default website by setting `State = Stopped`. + +```powershell +Configuration Sample_xWebsite_StopDefault +{ + param + ( + # Target nodes to apply the configuration + [string[]]$NodeName = 'localhost' + ) + # Import the module that defines custom resources + Import-DscResource -Module xWebAdministration + Node $NodeName + { + # Install the IIS role + WindowsFeature IIS + { + Ensure = "Present" + Name = "Web-Server" + } + # Stop the default website + xWebsite DefaultSite + { + Ensure = "Present" + Name = "Default Web Site" + State = "Stopped" + PhysicalPath = "C:\inetpub\wwwroot" + DependsOn = "[WindowsFeature]IIS" + } + } +} +``` + +### Create a new website + +While setting up IIS and stopping the default website is interesting, it isn’t quite useful yet. +After all, people typically use IIS to set up websites of their own with custom protocol and bindings. +Fortunately, using DSC, adding another website is as simple as using the File and xWebsite resources to copy the website content and configure the website. + +```powershell +Configuration Sample_xWebsite_NewWebsite +{ + param + ( + # Target nodes to apply the configuration + [string[]]$NodeName = 'localhost', + # Name of the website to create + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$WebSiteName, + # Source Path for Website content + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$SourcePath, + # Destination path for Website content + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [String]$DestinationPath + ) + # Import the module that defines custom resources + Import-DscResource -Module xWebAdministration + Node $NodeName + { + # Install the IIS role + WindowsFeature IIS + { + Ensure = "Present" + Name = "Web-Server" + } + # Install the ASP .NET 4.5 role + WindowsFeature AspNet45 + { + Ensure = "Present" + Name = "Web-Asp-Net45" + } + # Stop the default website + xWebsite DefaultSite + { + Ensure = "Present" + Name = "Default Web Site" + State = "Stopped" + PhysicalPath = "C:\inetpub\wwwroot" + DependsOn = "[WindowsFeature]IIS" + } + # Copy the website content + File WebContent + { + Ensure = "Present" + SourcePath = $SourcePath + DestinationPath = $DestinationPath + Recurse = $true + Type = "Directory" + DependsOn = "[WindowsFeature]AspNet45" + } + # Create the new Website with HTTPS + xWebsite NewWebsite + { + Ensure = "Present" + Name = $WebSiteName + State = "Started" + PhysicalPath = $DestinationPath + BindingInfo = MSFT_xWebBindingInformation + { + Protocol = "HTTPS" + Port = 8443 + CertificateThumbprint ="71AD93562316F21F74606F1096B85D66289ED60F" + CertificateStoreName = "WebHosting" + } + DependsOn = "[File]WebContent" + } + } +} +``` + +### Creating the default website using configuration data + +In this example, we’ve moved the parameters used to generate the website into a configuration data file. +All of the variant portions of the configuration are stored in a separate file. +This can be a powerful tool when using DSC to configure a project that will be deployed to multiple environments. +For example, users managing larger environments may want to test their configuration on a small number of machines before deploying it across many more machines in their production environment. + +Configuration files are made with this in mind. +This is an example configuration data file (saved as a .psd1). + +```powershell +Configuration Sample_xWebsite_FromConfigurationData +{ + # Import the module that defines custom resources + Import-DscResource -Module xWebAdministration + # Dynamically find the applicable nodes from configuration data + Node $AllNodes.where{$_.Role -eq "Web"}.NodeName + { + # Install the IIS role + WindowsFeature IIS + { + Ensure = "Present" + Name = "Web-Server" + } + # Install the ASP .NET 4.5 role + WindowsFeature AspNet45 + { + Ensure = "Present" + Name = "Web-Asp-Net45" + } + # Stop an existing website (set up in Sample_xWebsite_Default) + xWebsite DefaultSite + { + Ensure = "Present" + Name = "Default Web Site" + State = "Stopped" + PhysicalPath = $Node.DefaultWebSitePath + DependsOn = "[WindowsFeature]IIS" + } + # Copy the website content + File WebContent + { + Ensure = "Present" + SourcePath = $Node.SourcePath + DestinationPath = $Node.DestinationPath + Recurse = $true + Type = "Directory" + DependsOn = "[WindowsFeature]AspNet45" + } + # Create a new website + xWebsite BakeryWebSite + { + Ensure = "Present" + Name = $Node.WebsiteName + State = "Started" + PhysicalPath = $Node.DestinationPath + DependsOn = "[File]WebContent" + } + } +} +# Content of configuration data file (e.g. ConfigurationData.psd1) could be: +# Hashtable to define the environmental data +@{ + # Node specific data + AllNodes = @( + # All the WebServer has following identical information + @{ + NodeName = "*" + WebsiteName = "FourthCoffee" + SourcePath = "C:\BakeryWebsite\" + DestinationPath = "C:\inetpub\FourthCoffee" + DefaultWebSitePath = "C:\inetpub\wwwroot" + }, + @{ + NodeName = "WebServer1.fourthcoffee.com" + Role = "Web" + }, + @{ + NodeName = "WebServer2.fourthcoffee.com" + Role = "Web" + } + ); +} +# Pass the configuration data to configuration as follows: +Sample_xWebsite_FromConfigurationData -ConfigurationData ConfigurationData.psd1 +``` + +### All resources (end-to-end scenario) + +```powershell +# End to end sample for xWebAdministration + +configuration Sample_EndToEndxWebAdministration +{ + + Node $AllNodes.NodeName + { + # Create a Web Application Pool + xWebAppPool NewWebAppPool + { + Name = $Node.WebAppPoolName + Ensure = "Present" + State = "Started" + } + + #Create a New Website with Port + xWebSite NewWebSite + { + Name = $Node.WebSiteName + Ensure = "Present" + BindingInfo = MSFT_xWebBindingInformation + { + Port = $Node.Port + } + PhysicalPath = $Node.PhysicalPathWebSite + State = "Started" + DependsOn = @("[xWebAppPool]NewWebAppPool") + } + + #Create a new Web Application + xWebApplication NewWebApplication + { + Name = $Node.WebApplicationName + Website = $Node.WebSiteName + WebAppPool = $Node.WebAppPoolName + PhysicalPath = $Node.PhysicalPathWebApplication + Ensure = "Present" + DependsOn = @("[xWebSite]NewWebSite") + } + + #Create a new virtual Directory + xWebVirtualDirectory NewVirtualDir + { + Name = $Node.WebVirtualDirectoryName + Website = $Node.WebSiteName + WebApplication = $Node.WebApplicationName + PhysicalPath = $Node.PhysicalPathVirtualDir + Ensure = "Present" + DependsOn = @("[xWebApplication]NewWebApplication") + } + + File CreateWebConfig + { + DestinationPath = $Node.PhysicalPathWebSite + "\web.config" + Contents = "&amp;amp;amp;lt;?xml version=`"1.0`" encoding=`"UTF-8`"?&amp;amp;amp;gt; + &amp;amp;amp;lt;configuration&amp;amp;amp;gt; + &amp;amp;amp;lt;/configuration&amp;amp;amp;gt;" + Ensure = "Present" + DependsOn = @("[xWebVirtualDirectory]NewVirtualDir") + } + + xWebConfigKeyValue ModifyWebConfig + { + Ensure = "Present" + ConfigSection = "AppSettings" + KeyValuePair = @{key="key1";value="value1"} + IsAttribute = $false + WebsitePath = "IIS:\sites\" + $Node.WebsiteName + DependsOn = @("[File]CreateWebConfig") + } + } +} + +#You can place the below in another file to create multiple websites using the same configuration block. +$Config = @{ + AllNodes = @( + @{ + NodeName = "localhost"; + WebAppPoolName = "TestAppPool"; + WebSiteName = "TestWebSite"; + PhysicalPathWebSite = "C:\web\webSite"; + WebApplicationName = "TestWebApplication"; + PhysicalPathWebApplication = "C:\web\webApplication"; + WebVirtualDirectoryName = "TestVirtualDir"; + PhysicalPathVirtualDir = "C:\web\virtualDir"; + Port = 100 + } + ) + } + +Sample_EndToEndxWebAdministration -ConfigurationData $config +Start-DscConfiguration ./Sample_EndToEndxWebAdministration -wait -Verbose +``` diff --git a/TechNetDocumentation_xWebAdministration.html b/TechNetDocumentation_xWebAdministration.html deleted file mode 100644 index ee92a46ea..000000000 --- a/TechNetDocumentation_xWebAdministration.html +++ /dev/null @@ -1,1430 +0,0 @@ - -
-
-

- - - Introduction -
-
-

-
-

- - The xWebAdministration module is a part of the Windows PowerShell Desired State Configuration (DSC) Resource Kit, which is a collection of DSC Resources produced by the PowerShell Team. This module contains - the xIISModule, xWebAppPool, xWebsite, - xWebApplication, xWebVirtualDirectory & xWebConfigKeyValue resources. These DSC resources allow creation and configuration of various IIS artifacts. - -

-

- - All of the resources in the DSC Resource Kit are provided AS IS, and are not supported through any Microsoft standard support program or service. The "x" in xWebAdministration stands for experimental, which - means that these resources will be fix forward and monitored by the module owner(s). - -

-

Please leave comments, feature requests, and bug reports in the Q & A tab for this module.

-

- - If you would like to modify xWebAdministration module, feel free. When modifying, please update the module name, resource friendly name, and MOF class name (instructions below). As specified in the license, - you may copy or modify this resource as long as they are used on the Windows Platform. - -

-

- - For more information about Windows PowerShell Desired State Configuration, check out the blog posts on the - PowerShell Blog (this is a good starting point). There - are also great community resources, such as - PowerShell.org - , or PowerShell Magazine. For more information on the DSC Resource Kit, check out - this blog post. - -

-
-

- Installation - -
-
-

-
-

- To install xWebAdministration module: -

-
    -
  • - - Unzip the content under $env:ProgramFiles\WindowsPowerShell\Modules folder - -
  • -
-

To confirm installation:

-
    -
  • - - Run Get-DSCResource to see that - xIisModule, xWebAppPool, xWebsite, - xWebApplication, xWebVirtualDirectory & xWebConfigKeyValue are among the DSC Resources listed - -
  • -
-

- Requirements -

-

- - This module requires the latest version of PowerShell (v4.0, which ships in Windows 8.1 or Windows Server 2012R2). It also requires IIS features. To easily use PowerShell 4.0 on older operating systems, - - install WMF 4.0 - - .  Please read the installation instructions that are present on both the download page - and the release notes for WMF 4.0. - -

-

- Description -

-

- - The xWebAdministration module is a part of the Windows PowerShell Desired State Configuration (DSC) Resource Kit, which is a collection of DSC Resources produced by the PowerShell Team. This module contains - the xIISModule, xWebAppPool, xWebsite, - xWebApplication, xWebVirtualDirectory & xWebConfigKeyValue resources. These DSC resources allow creation and configuration of various IIS artifacts. - -   -

-

Details

-

- xIISModule resource has following properties: -

-
    -
  • - - Path:                        The path to the module to be registered. - -
  • -
  • - - Name:                      The logical name to register the module as in IIS. - -
  • -
  • - - RequestPath:                         The allowed request paths, such as *.php - -
  • -
  • - - Verb:                        An array of allowed verbs, such as get and post. - -
  • -
  • - - SiteName:                      The name of the Site to register the module for. If empty, the resource - will register the module with all of IIS. - -
  • -
  • - - ModuleType:                         The type of the module. Currently, only FastCgiModule - is supported. - -
  • -
  • - - Ensure:                         Should module be present or absent - -
  • -
-

- xWebAppPool resource has following properties: -

-
    -
  • - - Name:                        The desired name of the web application pool - -
  • -
  • - - Ensure:                      Should the application pool be present or absent - -
  • -
  • - - State:                         State of the application pool – started or stopped - -
  • -
-

- xWebsite resource has following properties: -

-
    -
  • - - Name - :                        - The desired name of the website   - -
  • -
  • - - PhysicalPath - :           -   The path to the files that compose the website - -
  • -
  • - - State - :                         - State of the website – started or stopped - -
  • -
  • - - BindingInfo - :             -   Website's binding information - -
  • -
  • - - ApplicationPool - :     -    The website’s application pool - -
  • -
  • - - Ensure - :                       - Should website be present or absent - -
  • -
-

- xWebApplication resource has following properties: -

-
    -
  • - - Website - :                    - Name of website with which web application is associated   - -
  • -
  • - - Name:                        The desired name of the web application - -
  • -
  • - - WebAppPool - :          -   Web application’s application pool  - -
  • -
  • - - PhysicalPath - :            - The path to the files that compose the web application - -
  • -
  • - - Ensure:                      Should web application be present or absent - -
  • -
-

- xWebVirtualDirectory resource has following properties: -

-
    -
  • - - Website - :                    - Name of website with which virtual directory is associated    - -
  • -
  • - - WebApplication - :     -   Web application name for the virtual directory - -
  • -
  • - - PhysicalPath - :           - The path to the files that compose the virtual directory - -
  • -
  • - - Name:                        The name of the virtual directory - -
  • -
  • - - Ensure:                      Ensures if the virtual directory is Present or Absent. - -
  • -
  • - - State:                         State of the application pool. Can be Started or Stopped. - -
  • -
-

- xWebConfigKeyValue resource has following properties: -

-
    -
  • - - WebsitePath - :           - Path to website location (IIS or WebAdministration format) - -
  • -
  • - - ConfigSection:         Section to update (only AppSettings supported as of now) - -
  • -
  • - - KeyValuePair:          Key value pair for AppSettings (ItemCollection format) - -
  • -
-

Renaming Requirements

-

When making changes to these resources, we suggest the following practice:

-
    -
  1. -

    - - Update the following names by replacing MSFT with your company/community name and replacing the - “x” with "c" (short for "Community") or another prefix of your choice: - -

    -
      -
    • - - Module name (ex: xWebAdministration becomes - cWebAdministration) - -
    • -
    • - - Resource folder (ex: MSFT_xWebsite becomes - Contoso_cWebsite) - -
    • -
    • - - Resource Name (ex: MSFT_xWebsite becomes - Contoso_cWebsite) - -
    • -
    • - - Resource Friendly Name (ex: xWebsite becomes - cWebsite) - -
    • -
    • - - MOF class name (ex: MSFT_xWebsite becomes - Contoso_cWebsite) - -
    • -
    • - - Filename for the <resource>.schema.mof (ex: MSFT_Website.schema.mof becomes - Contoso_cWebsite.schema.mof) - -
    • -
    -
  2. -
  3. -

    - Update module and metadata information in the module manifest -

    -
  4. -
  5. -

    - Update any configuration that use these resources -

    -
  6. -
-

- - - - We reserve resource and module names without prefixes ("x" or "c") for future use (e.g. "MSFT_WebAdministration" or "WebAdministration").  - If the next version of Windows Server ships with a "WebAdministration" resource, we don't want to break any configurations that use any community modifications.  Please keep a prefix such as "c" on all community modifications. - - - -

-

- Example: Registering Php - - - -
-
-
-
-

-

-   - - When configuring an IIS Application that uses PHP, you first need to register the PHP CGI module with - IIS.  The following xPhp configuration downloads and installs the prerequisites for PHP, downloads PHP, registers the PHP CGI module with IIS and sets the system environment variable that PHP needs to run. - -

-

 

-

- - Note: this sample is intended to be used as a composite resource, so it does not use Configuration Data. -   - Please see the - - - - Composite Configuration - Blog - - - on how to use this in configuration in another configuration. -

-
-
-
PowerShell
-
- Edit| - Remove -
- - -
-
# Composite configuration to install the IIS pre-requisites for php 
-Configuration IisPreReqs_php 
-{ 
-param 
-    ( 
-        [Parameter(Mandatory = $true)] 
-        [Validateset("Present","Absent")] 
-        [String] 
-        $Ensure 
-    )     
- 
-    foreach ($Feature in @("Web-Server","Web-Mgmt-Tools","web-Default-Doc", ` 
-"Web-Dir-Browsing","Web-Http-Errors","Web-Static-Content",` 
-            "Web-Http-Logging","web-Stat-Compression","web-Filtering",` 
-            "web-CGI","web-ISAPI-Ext","web-ISAPI-Filter")) 
-    { 
-        WindowsFeature "$Feature$Number" 
-        { 
-            Ensure = $Ensure 
-            Name = $Feature 
-        } 
-    } 
-} 
- 
-# Composite configuration to install PHP on IIS 
-configuration xPhp 
-{ 
-    param( 
-        [Parameter(Mandatory = $true)] 
-        [switch$installMySqlExt, 
- 
-        [Parameter(Mandatory = $true)] 
-        [string] $PackageFolder, 
- 
-        [Parameter(Mandatory = $true)] 
-        [string] $DownloadUri, 
- 
-        [Parameter(Mandatory = $true)] 
-        [string] $Vc2012RedistDownloadUri, 
- 
-        [Parameter(Mandatory = $true)] 
-        [String] $DestinationPath, 
- 
-        [Parameter(Mandatory = $true)] 
-        [string] $ConfigurationPath 
-    ) 
-        # Make sure the IIS Prerequisites for PHP are present 
-        IisPreReqs_php Iis 
-        { 
-            Ensure = "Present" 
- 
-            # Removed because this dependency does not work in  
-     # Windows Server 2012 R2 and below 
-            # This should work in WMF v5 and above 
-            # DependsOn = "[File]PackagesFolder" 
-        } 
- 
-        # Download and install Visual C Redist2012 from chocolatey.org 
-        Package vcRedist 
-        { 
-            Path = $Vc2012RedistDownloadUri 
-            ProductId = "{CF2BEA3C-26EA-32F8-AA9B-331F7E34BA97}" 
-            Name = "Microsoft Visual C++ 2012 x64 Minimum Runtime - 11.0.61030" 
-            Arguments = "/install /passive /norestart" 
-        } 
- 
-        $phpZip = Join-Path $PackageFolder "php.zip" 
- 
-        # Make sure the PHP archine is in the package folder 
-        xRemoteFile phpArchive 
-        { 
-            uri = $DownloadURI 
-            DestinationPath = $phpZip 
-        } 
- 
-        # Make sure the content of the PHP archine are in the PHP path 
-        Archive php 
-        { 
-            Path = $phpZip 
-            Destination  = $DestinationPath 
-        } 
- 
-        if ($installMySqlExt ) 
-        {                
-            # Make sure the MySql extention for PHP is in the main PHP path 
-            File phpMySqlExt 
-            { 
-                SourcePath = "$($DestinationPath)\ext\php_mysql.dll" 
-                DestinationPath = "$($DestinationPath)\php_mysql.dll" 
-                Ensure = "Present" 
-                DependsOn = @("[Archive]PHP") 
-                MatchSource = $true 
-            } 
-        } 
- 
-             
-            # Make sure the php.ini is in the Php folder 
-            File PhpIni 
-            { 
-                SourcePath = $ConfigurationPath 
-                DestinationPath = "$($DestinationPath)\php.ini" 
-                DependsOn = @("[Archive]PHP") 
-                MatchSource = $true 
-            } 
- 
- 
-            # Make sure the php cgi module is registered with IIS 
-            xIisModule phpHandler 
-            { 
-               Name = "phpFastCgi" 
-               Path = "$($DestinationPath)\php-cgi.exe" 
-               RequestPath = "*.php" 
-               Verb = "*" 
-               Ensure = "Present" 
-               DependsOn = @("[Package]vcRedist","[File]PhpIni")  
- 
-               # Removed because this dependency does not work in  
- # Windows Server 2012 R2 and below 
-            # This should work in WMF v5 and above 
-                # "[IisPreReqs_php]Iis"  
-            } 
- 
-        # Make sure the php binary folder is in the path 
-        Environment PathPhp 
-        { 
-            Name = "Path" 
-            Value = ";$($DestinationPath)" 
-            Ensure = "Present" 
-            Path = $true 
-            DependsOn = "[Archive]PHP" 
-        } 
-} 
- 
-xPhp -PackageFolder "C:\packages" ` 
-    -DownloadUri  -DownloadUri "http://windows.php.net/downloads/releases/php-5.5.13-Win32-VC11-x64.zip" ` 
-    -Vc2012RedistDownloadUri "http://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe" ` 
-    -DestinationPath "C:\php" ` 
-    -ConfigurationPath "C:\MyPhp.ini" ` 
-    -installMySqlExt $false  
-
-
-
-
-
 
-

 

-

- Example: Stopping the default website -

-

- - When configuring a new IIS Server, several references recommend removing or stopping the default website for security purposes. This example sets up your IIS webserver by installing IIS Windows Feature. Following that, it will - stop the default website by setting “State = Stopped ”. - -

-
-
-
PowerShell
-
- Edit| - Remove -
- - -
-
configuration Sample_xWebsite_StopDefault 
-{ 
-    param 
-    ( 
-        # Target nodes to apply the configuration 
-        [string[]]$NodeName = 'localhost' 
-    ) 
- 
-    # Import the module that defines custom resources 
-    Import-DscResource -Module xWebAdministration 
- 
-    Node $NodeName 
-    { 
-        # Install the IIS role 
-        WindowsFeature IIS 
-        { 
-            Ensure          = "Present" 
-            Name            = "Web-Server" 
-        } 
- 
-        # Stop the default website 
-        xWebsite DefaultSite  
-        { 
-            Ensure          = "Present" 
-            Name            = "Default Web Site" 
-            State           = "Stopped" 
-            PhysicalPath    = "C:\inetpub\wwwroot" 
-            DependsOn       = "[WindowsFeature]IIS" 
-        } 
-    } 
-}
-
-
-
-
-

- Example: Create a new website -

-
-

- - While setting up IIS and stopping the default website is interesting, it isn’t quite useful yet. After all, typically people use IIS to set up websites of their own with custom protocol and bindings. - Fortunately, using DSC, adding another website is as simple as using the File and xWebsite resources to copy the website content and configure the website. - -

-
-
-
-
PowerShell
-
- Edit| - Remove -
- - -
-
configuration Sample_xWebsite_NewWebsite 
-{ 
-    param 
-    ( 
-        # Target nodes to apply the configuration 
-        [string[]]$NodeName = 'localhost', 
- 
-        # Name of the website to create 
-        [Parameter(Mandatory)] 
-        [ValidateNotNullOrEmpty()] 
-        [String]$WebSiteName, 
- 
-        # Source Path for Website content 
-        [Parameter(Mandatory)] 
-        [ValidateNotNullOrEmpty()] 
-        [String]$SourcePath, 
- 
-        # Destination path for Website content 
-        [Parameter(Mandatory)] 
-        [ValidateNotNullOrEmpty()] 
-        [String]$DestinationPath 
-    ) 
- 
-    # Import the module that defines custom resources 
-    Import-DscResource -Module xWebAdministration 
- 
-    Node $NodeName 
-    { 
-        # Install the IIS role 
-        WindowsFeature IIS 
-        { 
-            Ensure          = "Present" 
-            Name            = "Web-Server" 
-        } 
- 
-        # Install the ASP .NET 4.5 role 
-        WindowsFeature AspNet45 
-        { 
-            Ensure          = "Present" 
-            Name            = "Web-Asp-Net45" 
-        } 
- 
-        # Stop the default website 
-        xWebsite DefaultSite  
-        { 
-            Ensure          = "Present" 
-            Name            = "Default Web Site" 
-            State           = "Stopped" 
-            PhysicalPath    = "C:\inetpub\wwwroot" 
-            DependsOn       = "[WindowsFeature]IIS" 
-        } 
- 
-        # Copy the website content 
-        File WebContent 
-        { 
-            Ensure          = "Present" 
-            SourcePath      = $SourcePath 
-            DestinationPath = $DestinationPath 
-            Recurse         = $true 
-            Type            = "Directory" 
-            DependsOn       = "[WindowsFeature]AspNet45" 
-        }        
- 
-        # Create the new Website with HTTPS 
-        xWebsite NewWebsite 
-        { 
-            Ensure          = "Present" 
-            Name            = $WebSiteName 
-            State           = "Started" 
-            PhysicalPath    = $DestinationPath 
-            BindingInfo     = MSFT_xWebBindingInformation 
-                             { 
-                               Protocol              = "HTTPS" 
-                               Port                  = 8443 
-                               CertificateThumbprint ="71AD93562316F21F74606F1096B85D66289ED60F" 
-                               CertificateStoreName  = "WebHosting" 
-                             } 
-            DependsOn       = "[File]WebContent" 
-        } 
-    } 
-} 
-
-
-
-
-
 
-

Example: Creating the default website using configuration data

-
-

- - In this example, we’ve moved the parameters used to generate the website into a configuration data file – all of the variant portions of the configuration are stored in a separate file. This - can be a powerful tool when using DSC to configure a project that will be deployed to multiple environments. For example, users managing larger environments may want to test their configuration on a small number of machines before deploying it across many - more machines in their production environment.
-
- Configuration files are made with this in mind. This is an example configuration data file (saved as a .psd1).   -
-

-
-
-
-
PowerShell
-
- Edit| - Remove -
- - -
-
configuration Sample_xWebsite_FromConfigurationData 
-{ 
-    # Import the module that defines custom resources 
-    Import-DscResource -Module xWebAdministration 
- 
-    # Dynamically find the applicable nodes from configuration data 
-    Node $AllNodes.where{$_.Role -eq "Web"}.NodeName 
-    { 
-        # Install the IIS role 
-        WindowsFeature IIS 
-        { 
-            Ensure          = "Present" 
-            Name            = "Web-Server" 
-        } 
- 
-        # Install the ASP .NET 4.5 role 
-        WindowsFeature AspNet45 
-        { 
-            Ensure          = "Present" 
-            Name            = "Web-Asp-Net45" 
-        } 
- 
-        # Stop an existing website (set up in Sample_xWebsite_Default) 
-        xWebsite DefaultSite  
-        { 
-            Ensure          = "Present" 
-            Name            = "Default Web Site" 
-            State           = "Stopped" 
-            PhysicalPath    = $Node.DefaultWebSitePath 
-            DependsOn       = "[WindowsFeature]IIS" 
-        } 
- 
-        # Copy the website content 
-        File WebContent 
-        { 
-            Ensure          = "Present" 
-            SourcePath      = $Node.SourcePath 
-            DestinationPath = $Node.DestinationPath 
-            Recurse         = $true 
-            Type            = "Directory" 
-            DependsOn       = "[WindowsFeature]AspNet45" 
-        }        
- 
-        # Create a new website 
-        xWebsite BakeryWebSite  
-        { 
-            Ensure          = "Present" 
-            Name            = $Node.WebsiteName 
-            State           = "Started" 
-            PhysicalPath    = $Node.DestinationPath 
-            DependsOn       = "[File]WebContent" 
-        } 
-    } 
-} 
- 
-# Content of configuration data file (e.g. ConfigurationData.psd1) could be: 
- 
-# Hashtable to define the environmental data 
-@{ 
-    # Node specific data 
-    AllNodes = @( 
- 
-       # All the WebServer has following identical information  
-       @{ 
-            NodeName           = "*" 
-            WebsiteName        = "FourthCoffee" 
-            SourcePath         = "C:\BakeryWebsite\" 
-            DestinationPath    = "C:\inetpub\FourthCoffee" 
-            DefaultWebSitePath = "C:\inetpub\wwwroot" 
-       }, 
- 
-       @{ 
-            NodeName           = "WebServer1.fourthcoffee.com" 
-            Role               = "Web" 
-        }, 
- 
-       @{ 
-            NodeName           = "WebServer2.fourthcoffee.com" 
-            Role               = "Web" 
-        } 
-    ); 
-} 
- 
-# Pass the configuration data to configuration as follows: 
-Sample_xWebsite_FromConfigurationData -ConfigurationData ConfigurationData.psd1
-
-
-
-
-

- - Example: All Resources (end to end scenario)
-
-

-

-
-
-
PowerShell
-
- Edit| - Remove -
- - -
-
# End to end sample for xWebAdministration  
-  
-configuration Sample_EndToEndxWebAdministration 
-{ 
-  
-    Node $AllNodes.NodeName 
-    { 
-        # Create a Web Application Pool 
-        xWebAppPool NewWebAppPool 
-        { 
-            Name   = $Node.WebAppPoolName 
-            Ensure = "Present" 
-            State  = "Started" 
-        } 
-  
-        #Create a New Website with Port 
-        xWebSite NewWebSite 
-        { 
-            Name   = $Node.WebSiteName 
-            Ensure = "Present" 
-            BindingInfo = MSFT_xWebBindingInformation 
-                        { 
-                            Port = $Node.Port 
-                        } 
-            PhysicalPath = $Node.PhysicalPathWebSite 
-            State = "Started" 
-            DependsOn = @("[xWebAppPool]NewWebAppPool") 
-        } 
-       
-        #Create a new Web Application 
-        xWebApplication NewWebApplication 
-        { 
-            Name = $Node.WebApplicationName 
-            Website = $Node.WebSiteName 
-            WebAppPool =  $Node.WebAppPoolName 
-            PhysicalPath = $Node.PhysicalPathWebApplication 
-            Ensure = "Present" 
-            DependsOn = @("[xWebSite]NewWebSite") 
-        } 
-  
-        #Create a new virtual Directory 
-        xWebVirtualDirectory NewVirtualDir 
-        { 
-            Name = $Node.WebVirtualDirectoryName 
-            Website = $Node.WebSiteName 
-            WebApplication =  $Node.WebApplicationName 
-            PhysicalPath = $Node.PhysicalPathVirtualDir 
-            Ensure = "Present" 
-            DependsOn = @("[xWebApplication]NewWebApplication") 
-        } 
-  
-        File CreateWebConfig 
-        { 
-         DestinationPath = $Node.PhysicalPathWebSite + "\web.config" 
-         Contents = "<?xml version=`"1.0`" encoding=`"UTF-8`"?> 
-                        <configuration> 
-                        </configuration>" 
-                Ensure = "Present" 
-         DependsOn = @("[xWebVirtualDirectory]NewVirtualDir") 
-        } 
-  
-        xWebConfigKeyValue ModifyWebConfig 
-        { 
-          Ensure = "Present" 
-          ConfigSection = "AppSettings" 
-          KeyValuePair = @{key="key1";value="value1"} 
-          IsAttribute = $false 
-          WebsitePath = "IIS:\sites\" + $Node.WebsiteName 
-          DependsOn = @("[File]CreateWebConfig") 
-        } 
-    } 
-} 
- 
-  
-#You can place the below in another file to create multiple websites using the same configuration block.  
- 
-$Config = @{ 
- 
-    AllNodes = @( 
-        @{ 
-            NodeName = "localhost"; 
-            WebAppPoolName = "TestAppPool"; 
-            WebSiteName = "TestWebSite"; 
-            PhysicalPathWebSite = "C:\web\webSite"; 
-            WebApplicationName = "TestWebApplication"; 
-            PhysicalPathWebApplication = "C:\web\webApplication"; 
-            WebVirtualDirectoryName = "TestVirtualDir"; 
-            PhysicalPathVirtualDir = "C:\web\virtualDir"; 
-            Port = 100 
-          } 
-      ) 
-   } 
-   
-Sample_EndToEndxWebAdministration -ConfigurationData $config 
- 
-Start-DscConfiguration ./Sample_EndToEndxWebAdministration -wait -Verbose 
-
-
-
-
-
 
-

-

Versions

-
-

1.0.0.0

-
-
-
    -
  • -

    - Initial release with the following resources -

    -
      -
    • -

      - xWebsite -

      -
    • -
    -
  • -
-
-
-

- 1.1.0.0 -

-
    -
  • -

    - Added support for HTTPS protocol -

    -
  • -
-
    -
  • -

    - Updated binding information to include Certificate inforation for HTTPS -

    -
  • -
  • -

    - Removed protocol property. Protocol is included in binding information -

    -
  • -
-
    -
  • -

    Bug fixes

    -
  • -
- -

1.2

-
-
    -
  • - Added the - - xWebAppPool, -   - xWebApplication, xWebVirtualDirectory & xWebConfigKeyValue - -
  • -
-

1.3.2

-
    -
  • Added xIisModule
  • -
-

1.3.2.1

-
    -
  • Documentation-only change, added metadata to module manifest
  • -
-

1.3.2.2

-
    -
  • Documentation only change. Module manifest metadata changed to improve PowerShell Gallery experience.
  • -
-

1.3.2.3

-
    -
  • Fixed variable name typo in MSFT_xIisModule.
  • -
  • Added OutputType attribute to Test-TargetResource and Get-TargetResource in MSFT_xWebSite.
  • -
-

1.3.2.4

-
    -
  • Fixed the confusion with mismatched versions and xWebDeploy resources
  • -
  • Removed BakeryWebsite.zip for legal reasons. Please read Examples\README.md for the workaround.
  • -
-

1.3.2.5

-
    -
  • Changed Key property in MSFT_xWebConfigKeyValue to be a Key, instead of Required. This allows multiple keys to be configured within the same web.config file.
  • -
- -   - -
-
-
-
- -
- - \ No newline at end of file diff --git a/Tests/Integration/IISServerLevel_Configuration.ps1 b/Tests/Integration/IISServerLevel_Configuration.ps1 new file mode 100644 index 000000000..1cea52969 --- /dev/null +++ b/Tests/Integration/IISServerLevel_Configuration.ps1 @@ -0,0 +1,168 @@ +configuration ManagedRuntimeVersion +{ + Import-DscResource -ModuleName xWebAdministration + + xWebAppPoolDefaults PoolDefaults + { + ApplyTo = "Machine" + ManagedRuntimeVersion = "$env:PesterManagedRuntimeVersion" + } +} + +configuration InvalidManagedRuntimeVersion +{ + Import-DscResource -ModuleName xWebAdministration + + xWebAppPoolDefaults PoolDefaults + { + ApplyTo = "Machine" + ManagedRuntimeVersion = "v1.5" + } +} + +configuration AppPoolIdentityType +{ + Import-DscResource -ModuleName xWebAdministration + + xWebAppPoolDefaults PoolDefaults + { + ApplyTo = "Machine" + IdentityType = "$env:PesterApplicationPoolIdentity" + } +} + +configuration LogFormat +{ + Import-DscResource -ModuleName xWebAdministration + + xWebSiteDefaults LogFormat + { + ApplyTo = "Machine" + LogFormat = "$env:PesterLogFormat" + } +} + +configuration DefaultPool +{ + Import-DscResource -ModuleName xWebAdministration + + xWebSiteDefaults DefaultPool + { + ApplyTo = "Machine" + DefaultApplicationPool = "$env:PesterDefaultPool" + } +} + +configuration virtualDirectoryDefaults +{ + Import-DscResource -ModuleName xWebAdministration + + xWebSiteDefaults virtualDirectoryDefaults + { + ApplyTo = "Machine" + AllowSubDirConfig = "$env:PesterVirtualDirectoryDefaults" + } +} + +configuration AddMimeType +{ + Import-DscResource -ModuleName xWebAdministration + + xIIsMimeTypeMapping AddMimeType + { + Extension = ".PesterDummy" + MimeType = "text/plain" + Ensure = "Present" + } +} + +configuration AddMimeType2 +{ + Import-DscResource -ModuleName xWebAdministration + + xIIsMimeTypeMapping AddMimeType2 + { + Extension = $env:PesterFileExtension2 + MimeType = "$env:PesterMimeType2" + Ensure = "Present" + } +} + +configuration RemoveMimeType +{ + Import-DscResource -ModuleName xWebAdministration + + xIIsMimeTypeMapping RemoveMimeType + { + Extension = $env:PesterFileExtension + MimeType = "$env:PesterMimeType" + Ensure = "Absent" + } +} + +configuration RemoveMimeType2 +{ + Import-DscResource -ModuleName xWebAdministration + + xIIsMimeTypeMapping RemoveMimeType2 + { + Extension = ".PesterDummy2" + MimeType = "text/dummy" + Ensure = "Absent" + } +} + +configuration AllowDelegation +{ + Import-DscResource -ModuleName xWebAdministration + + xIisFeatureDelegation AllowDelegation + { + SectionName = "security/authentication/anonymousAuthentication" + OverrideMode = "Allow" + } +} + +configuration DenyDelegation +{ + Import-DscResource -ModuleName xWebAdministration + + xIisFeatureDelegation DenyDelegation + { + SectionName = "defaultDocument" + OverrideMode = "Deny" + } +} + +configuration RemoveHandler +{ + Import-DscResource -ModuleName xWebAdministration + + xIisHandler TRACEVerbHandler + { + Name = "TRACEVerbHandler" + Ensure = "Absent" + } +} + +configuration AddHandler +{ + Import-DscResource -ModuleName xWebAdministration + + xIisHandler WebDAV + { + Name = "WebDAV" + Ensure = "Present" + } +} + +configuration StaticFileHandler +{ + Import-DscResource -ModuleName xWebAdministration + + xIisHandler StaticFile + { + Name = "StaticFile" + Ensure = "Present" + } +} diff --git a/Tests/Integration/MSFT_xIISServerLevelIntegration.Tests.ps1 b/Tests/Integration/MSFT_xIISServerLevelIntegration.Tests.ps1 new file mode 100644 index 000000000..2102848e3 --- /dev/null +++ b/Tests/Integration/MSFT_xIISServerLevelIntegration.Tests.ps1 @@ -0,0 +1,363 @@ +###################################################################################### +# Integration Tests for DSC Resource for IIS Server level defaults +# +# These tests change the IIS server level configuration but roll back the changes at the end +# so they should be save to run. +# Run as an elevated administrator +# At this time, we don't have tests for all changable properties, but it should be easy to add more tests. +###################################################################################### + +# Check if WebServer is Installed +if (@(Get-WindowsOptionalFeature -Online -FeatureName 'IIS-WebServer' ` + | Where-Object -Property State -eq 'Disabled').Count -gt 0) +{ + if ((Get-CimInstance Win32_OperatingSystem).ProductType -eq 1) + { + # Desktop OS + Enable-WindowsOptionalFeature -Online -FeatureName 'IIS-WebServer' + } + else + { + # Server OS + Install-WindowsFeature -IncludeAllSubFeature -IncludeManagementTools -Name 'Web-Server' + } +} + +$DSCModuleName = 'xWebAdministration' + +$moduleRoot = "${env:ProgramFiles}\WindowsPowerShell\Modules\$DSCModuleName" + +if(-not (Test-Path -Path $moduleRoot)) +{ + $null = New-Item -Path $moduleRoot -ItemType Directory +} +else +{ + # Copy the existing folder out to the temp directory to hold until the end of the run + # Delete the folder to remove the old files. + $tempLocation = Join-Path -Path $env:Temp -ChildPath $DSCModuleName + Copy-Item -Path $moduleRoot -Destination $tempLocation -Recurse -Force + Remove-Item -Path $moduleRoot -Recurse -Force + $null = New-Item -Path $moduleRoot -ItemType Directory +} + +Copy-Item -Path $PSScriptRoot\..\..\* -Destination $moduleRoot -Recurse -Force -Exclude '.git' + +if (Get-Module -Name $DSCModuleName -All) +{ + Get-Module -Name $DSCModuleName -All | Remove-Module +} + +Import-Module -Name $(Get-Item -Path (Join-Path $moduleRoot -ChildPath "$DSCModuleName.psd1")) -Force + +if (($env:PSModulePath).Split(';') -ccontains $pwd.Path) +{ + $script:tempPath = $env:PSModulePath + $env:PSModulePath = ($env:PSModulePath -split ';' | Where-Object {$_ -ne $pwd.path}) -join ';' +} + + +$executionPolicy = Get-ExecutionPolicy +if ($executionPolicy -ne 'Unrestricted') +{ + Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Force + $rollbackExecution = $true +} + +try +{ + # Now that xWebAdministration should be discoverable load the configuration data + . "$PSScriptRoot\IISServerLevel_Configuration.ps1" + + # create a unique name that we use for our temp files and folders + [string]$tempName = "xIISServerLevelTests_" + (Get-Date).ToString("yyyyMMdd_HHmmss") + + # some constants + [string]$constPsPath = 'MACHINE/WEBROOT/APPHOST' + [string]$constAPDFilter = "system.applicationHost/applicationPools/applicationPoolDefaults" + [string]$constSiteFilter = "system.applicationHost/sites/" + + Describe "xIISServerDefaults" { + function GetSiteValue([string]$path,[string]$name) + { + return (Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.applicationHost/sites/$path" -name $name).value + } + + It 'Checking resource: xWebSiteDefaults' -test { + (Get-DSCResource -name xWebSiteDefaults).count | should be 1 + } + It 'Checking resource: xWebAppPoolDefaults' -test { + (Get-DSCResource -name xWebAppPoolDefaults).count | should be 1 + } + It 'Checking resource: xIisFeatureDelegation' -test { + (Get-DSCResource -name xIisFeatureDelegation).count | should be 1 + } + It 'Checking resource: xIisMimeTypeMapping' -test { + + (Get-DSCResource -name xIisMimeTypeMapping).count | should be 1 + } + + # before doing our changes, create a backup of the current config + Backup-WebConfiguration -Name $tempName + + It 'Changing ManagedRuntimeVersion ' -test { + { + # get the current value + [string]$originalValue = (Get-WebConfigurationProperty -pspath $constPsPath -filter $constAPDFilter -name managedRuntimeVersion) + + # We are using environment variables here, because a inline PowerShell variable was empty after executing Start-DscConfiguration + + # change the value to something else + if ($originalValue -eq "v4.0") + { + $env:PesterManagedRuntimeVersion = "v2.0" + } + else + { + $env:PesterManagedRuntimeVersion = "v4.0" + } + + # define the configuration + # we need to set the PSModulePath once more to get this to work in AppVevor to find our resources + [System.Environment]::SetEnvironmentVariable('PSModulePath',$env:PSModulePath,[System.EnvironmentVariableTarget]::Machine) + + # execute the configuration into a temp location + ManagedRuntimeVersion -OutputPath $env:temp\$($tempName)_ManagedRuntimeVersion + # run the configuration, it should not throw any errors + Start-DscConfiguration -Path $env:temp\$($tempName)_ManagedRuntimeVersion -Wait -Verbose -ErrorAction Stop -Force + } | should not throw + + # get the configured value again + $changedValue = (Get-WebConfigurationProperty -pspath $constPsPath -filter $constAPDFilter -name managedRuntimeVersion).Value + + # compare it to the one we just tried to set. + $changedValue | should be $env:PesterManagedRuntimeVersion + } + + + It 'Invalid ManagedRuntimeVersion ' -Test { + { + InvalidManagedRuntimeVersion -OutputPath $env:temp\$($tempName)_InvalidManagedRuntimeVersion + Start-DscConfiguration -Path $env:temp\$($tempName)_ManagedRuntimeVersion -Wait -Verbose -ErrorAction Stop -Force + } | should throw + } + + It 'Changing IdentityType' -test { + { + # get the current value + [string]$originalValue = (Get-WebConfigurationProperty -pspath $constPsPath -filter $constAPDFilter/processModel -name identityType) + + if ($originalValue -eq "ApplicationPoolIdentity") + { + $env:PesterApplicationPoolIdentity = "LocalService" + } + else + { + $env:PesterApplicationPoolIdentity = "ApplicationPoolIdentity" + } + + AppPoolIdentityType -OutputPath $env:temp\$($tempName)_AppPoolIdentityType + Start-DscConfiguration -Path $env:temp\$($tempName)_AppPoolIdentityType -Wait -Verbose -ErrorAction Stop -Force} | should not throw + $changedValue = (Get-WebConfigurationProperty -pspath $constPsPath -filter $constAPDFilter/processModel -name identityType) + + $changedValue | should be $env:PesterApplicationPoolIdentity + } + + + It 'Changing LogFormat' -test { + { + # get the current value + + [string]$originalValue = GetSiteValue "logFile" "logFormat" + + if ($originalValue -eq "W3C") + { + $env:PesterLogFormat = "IIS" + } + else + { + $env:PesterLogFormat = "W3C" + } + + LogFormat -OutputPath $env:temp\$($tempName)_LogFormat + Start-DscConfiguration -Path $env:temp\$($tempName)_LogFormat -Wait -Verbose -ErrorAction Stop -Force} | should not throw + $changedValue = GetSiteValue "logFile" "logFormat" + + $changedValue | should be $env:PesterALogFormat + } + + It 'Changing Default AppPool' -test { + { + # get the current value + + [string]$originalValue = GetSiteValue "applicationDefaults" "applicationPool" + + $env:PesterDefaultPool = "fooBar" + + DefaultPool -OutputPath $env:temp\$($tempName)_LogFormat + Start-DscConfiguration -Path $env:temp\$($tempName)_LogFormat -Wait -Verbose -ErrorAction Stop -Force} | should not throw + $changedValue = GetSiteValue "applicationDefaults" "applicationPool" + $changedValue | should be $env:PesterDefaultPool + } + + It 'Changing Default virtualDirectoryDefaults' -test { + { + # get the current value + + [string]$originalValue = GetSiteValue "virtualDirectoryDefaults" "allowSubDirConfig" + + if ($originalValue -eq "true") + { + $env:PesterVirtualDirectoryDefaults = "false" + } + else + { + $env:PesterVirtualDirectoryDefaults = "true" + } + + virtualDirectoryDefaults -OutputPath $env:temp\$($tempName)_LogFormat + Start-DscConfiguration -Path $env:temp\$($tempName)_LogFormat -Wait -Verbose -ErrorAction Stop -Force} | should not throw + $changedValue = GetSiteValue "virtualDirectoryDefaults" "allowSubDirConfig" + $changedValue | should be $env:PesterVirtualDirectoryDefaults + } + + It 'Adding a new MimeType' -test { + { + AddMimeType -OutputPath $env:temp\$($tempName)_AddMimeType + Start-DscConfiguration -Path $env:temp\$($tempName)_AddMimeType -Wait -Verbose -ErrorAction Stop -Force} | should not throw + + [string]$filter = "system.webServer/staticContent/mimeMap[@fileExtension='.PesterDummy' and @mimeType='text/plain']" + ((Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter $filter -Name .) | Measure).Count | should be 1 + } + + It 'Adding an existing MimeType' -test { + { + $node = (Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/staticContent/mimeMap" -Name .) | Select -First 1 + $env:PesterFileExtension2 = $node.fileExtension + $env:PesterMimeType2 = $node.mimeType + + AddMimeType2 -OutputPath $env:temp\$($tempName)_AddMimeType2 + Start-DscConfiguration -Path $env:temp\$($tempName)_AddMimeType2 -Wait -Verbose -ErrorAction Stop -Force} | should not throw + + [string]$filter = "system.webServer/staticContent/mimeMap[@fileExtension='" + $env:PesterFileExtension2 + "' and @mimeType='" + "$env:PesterMimeType2" + "']" + ((Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter $filter -Name .) | Measure).Count | should be 1 + } + + It 'Removing a MimeType' -test { + { + $node = (Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/staticContent/mimeMap" -Name .) | Select -First 1 + $env:PesterFileExtension = $node.fileExtension + $env:PesterMimeType = $node.mimeType + + RemoveMimeType -OutputPath $env:temp\$($tempName)_RemoveMimeType + Start-DscConfiguration -Path $env:temp\$($tempName)_RemoveMimeType -Wait -Verbose -ErrorAction Stop -Force} | should not throw + + [string]$filter = "system.webServer/staticContent/mimeMap[@fileExtension='" + $env:PesterFileExtension + "' and @mimeType='" + "$env:PesterMimeType" + "']" + ((Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter $filter -Name .) | Measure).Count | should be 0 + } + + It 'Removing a non existing MimeType' -test { + { + RemoveMimeType2 -OutputPath $env:temp\$($tempName)_RemoveMimeType2 + Start-DscConfiguration -Path $env:temp\$($tempName)_RemoveMimeType2 -Wait -Verbose -ErrorAction Stop -Force} | should not throw + } + + # Allow Feature Delegation + # for this test we are using the anonymous Authentication feature, which is installed by default, but has Feature Delegation set to denied by default + if ((Get-WindowsOptionalFeature –Online | Where {$_.FeatureName -eq "IIS-Security" -and $_.State -eq "Enabled"}).Count -eq 1) + { + if ((Get-WebConfiguration /system.webserver/security/authentication/anonymousAuthentication iis:\).OverrideModeEffective -eq 'Deny') + { + It 'Allow Feature Delegation' -test { + { + AllowDelegation -OutputPath $env:temp\$($tempName)_AllowDelegation + Start-DscConfiguration -Path $env:temp\$($tempName)_AllowDelegation -Wait -Verbose -ErrorAction Stop } | should not throw + + (Get-WebConfiguration /system.webserver/security/authentication/anonymousAuthentication iis:\).OverrideModeEffective | Should be 'Allow' + } + } + } + + It 'Deny Feature Delegation' -test { + { + # this test doesn't really test the resource if it defaultDocument + # is already Deny (not the default) + # well it doesn't test the Set Method, but does test the Test method + # What if the default document module is not installed? + + DenyDelegation -OutputPath $env:temp\$($tempName)_DenyDelegation + Start-DscConfiguration -Path $env:temp\$($tempName)_DenyDelegation -Wait -Verbose -ErrorAction Stop + + # Now lets try to add a new default document on site level, this should fail + # get the first site, it doesn't matter which one, it should fail. + $siteName = (Get-ChildItem iis:\sites | Select -First 1).Name + Add-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST/$siteName" -filter "system.webServer/defaultDocument/files" -name "." -value @{value='pesterpage.cgi'} + + # remove it again, should also fail, but if both work we at least cleaned it up, it would be better to backup and restore the web.config file. + Remove-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST/$siteName" -filter "system.webServer/defaultDocument/files" -name "." -AtElement @{value='pesterpage.cgi'} } | should throw + } + + # Handler Tests + + It 'Remove a handler' -test { + { + # TRACEVerbHandler is usually there, remove it + + RemoveHandler -OutputPath $env:temp\$($tempName)_RemoveHandler + Start-DscConfiguration -Path $env:temp\$($tempName)_RemoveHandler -Wait -Verbose -ErrorAction Stop} | should not throw + + [string]$filter = "system.webServer/handlers/Add[@Name='TRACEVerbHandler']" + ((Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter $filter -Name .) | Measure).Count | should be 0 + + } + + It 'Add a handler' -test { + { + # webDav is normally not there, and even if the WebDav feature is not installed + # we can add a handler for it. + + AddHandler -OutputPath $env:temp\$($tempName)_AddHandler + Start-DscConfiguration -Path $env:temp\$($tempName)_AddHandler -Wait -Verbose -ErrorAction Stop} | should not throw + + [string]$filter = "system.webServer/handlers/Add[@Name='WebDAV']" + ((Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter $filter -Name .) | Measure).Count | should be 1 + + } + + It 'StaticFile handler' -test { + { + # StaticFile is usually there, have it present shouldn't change anything. + + StaticFileHandler -OutputPath $env:temp\$($tempName)_StaticFileHandler + Start-DscConfiguration -Path $env:temp\$($tempName)_StaticFileHandler -Wait -Verbose -ErrorAction Stop} | should not throw + + [string]$filter = "system.webServer/handlers/Add[@Name='StaticFile']" + ((Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter $filter -Name .) | Measure).Count | should be 1 + + } + } +} +finally +{ + # roll back our changes + Restore-WebConfiguration -Name $tempName + Remove-WebConfigurationBackup -Name $tempName + + # remove our result variables + Get-ChildItem env: | Where Name -match "^Pester" | Remove-Item + + # remove the generated MoF files + Get-ChildItem $env:temp -Filter $tempName* | Remove-item -Recurse + + # Cleanup after the test + Remove-Item -Path $moduleRoot -Recurse -Force + + if ($rollbackExecution) + { + Set-ExecutionPolicy -ExecutionPolicy $executionPolicy -Force + } + + if ($script:tempPath) { + $env:PSModulePath = $script:tempPath + } +} diff --git a/Tests/Integration/MSFT_xWebBindingInformation.Tests.ps1 b/Tests/Integration/MSFT_xWebBindingInformation.Tests.ps1 new file mode 100644 index 000000000..f1da39514 --- /dev/null +++ b/Tests/Integration/MSFT_xWebBindingInformation.Tests.ps1 @@ -0,0 +1,110 @@ +# Check if WebServer is Installed +if (@(Get-WindowsOptionalFeature -Online -FeatureName 'IIS-WebServer' ` + | Where-Object -Property State -eq 'Disabled').Count -gt 0) +{ + if ((Get-CimInstance Win32_OperatingSystem).ProductType -eq 1) + { + # Desktop OS + Enable-WindowsOptionalFeature -Online -FeatureName 'IIS-WebServer' + } + else + { + # Server OS + Install-WindowsFeature -IncludeAllSubFeature -IncludeManagementTools -Name 'Web-Server' + } +} + +$DSCModuleName = 'xWebAdministration' + +$moduleRoot = "${env:ProgramFiles}\WindowsPowerShell\Modules\$DSCModuleName" + +if(-not (Test-Path -Path $moduleRoot)) +{ + $null = New-Item -Path $moduleRoot -ItemType Directory +} +else +{ + # Copy the existing folder out to the temp directory to hold until the end of the run + # Delete the folder to remove the old files. + $tempLocation = Join-Path -Path $env:Temp -ChildPath $DSCModuleName + Copy-Item -Path $moduleRoot -Destination $tempLocation -Recurse -Force + Remove-Item -Path $moduleRoot -Recurse -Force + $null = New-Item -Path $moduleRoot -ItemType Directory +} + +Copy-Item -Path $PSScriptRoot\..\..\* -Destination $moduleRoot -Recurse -Force -Exclude '.git' + +if (Get-Module -Name $DSCModuleName -All) +{ + Get-Module -Name $DSCModuleName -All | Remove-Module +} + +Import-Module -Name $(Get-Item -Path (Join-Path $moduleRoot -ChildPath 'xWebadministration.psd1')) -Force + +# This fixes a bug in AppVeyor where it was picking up duplicates of the code +if (($env:PSModulePath).Split(';') -ccontains $pwd.Path) +{ + $script:tempPath = $env:PSModulePath + $env:PSModulePath = ($env:PSModulePath -split ';' | Where-Object {$_ -ne $pwd.path}) -join ';' +} + +$executionPolicy = Get-ExecutionPolicy +if ($executionPolicy -ne 'Unrestricted') +{ + Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Force + $rollbackExecution = $true +} + +try +{ + # Now that xWebAdministration should be discoverable load the configuration data + . "$PSScriptRoot\WebBindingInformation_Config.ps1" + + Describe 'MSFT_xWebBindingInformation' { + It 'Should be able to get xWebsite' -test { + # just a good idea. + # I thought it might force the classes to register, but it does not. + $resources = Get-DscResource -Name xWebsite + $resources.count | should be 1 + } + + It 'Should compile and run without throwing' -Test { + { + # Force Cim Classes to register + # Update the system environment path so that LCM will load the module + # Requires WMF 5 + [System.Environment]::SetEnvironmentVariable('PSModulePath',$env:PSModulePath,[System.EnvironmentVariableTarget]::Machine) + + WebBindingInfo -OutputPath $env:temp\WebBindingInfo + Start-DscConfiguration -Path $env:temp\WebBindingInfo -Wait -Verbose -ErrorAction Stop + } | should not throw + } + + # Directly interacting with Cim classes is not supported by PowerShell DSC + # it is being done here explicitly for the purpose of testing. Please do not + # do this in actual resource code + $xWebBindingInforationClass = (Get-CimClass -Namespace 'root/microsoft/Windows/DesiredStateConfiguration' -ClassName 'MSFT_xWebBindingInformation') + $storeNames = (Get-CimClass -Namespace 'root/microsoft/Windows/DesiredStateConfiguration' -ClassName 'MSFT_xWebBindingInformation').CimClassProperties['CertificateStoreName'].Qualifiers['Values'].Value + + foreach ($storeName in $storeNames) + { + It "Uses valid credential store: $storeName" { + (Join-Path -Path Cert:\LocalMachine -ChildPath $storeName) | Should Exist + } + } + } + + # Cleanup after the test + Remove-Item -Path $moduleRoot -Recurse -Force +} +finally +{ + if ($rollbackExecution) + { + Set-ExecutionPolicy -ExecutionPolicy $executionPolicy -Force + } + + if ($script:tempPath) { + $env:PSModulePath = $script:tempPath + } +} diff --git a/Tests/Integration/WebBindingInformation_Config.ps1 b/Tests/Integration/WebBindingInformation_Config.ps1 new file mode 100644 index 000000000..ad754c813 --- /dev/null +++ b/Tests/Integration/WebBindingInformation_Config.ps1 @@ -0,0 +1,11 @@ +configuration WebBindingInfo +{ + Import-DscResource -ModuleName xWebAdministration + + xWebsite WebBindingInfo + { + Name = 'foobar' + Ensure = 'absent' + PhysicalPath = "$env:temp\WebBindingInfo" + } +} diff --git a/Tests/Unit/MSFT_xWebVirtualDirectory.tests.ps1 b/Tests/Unit/MSFT_xWebVirtualDirectory.tests.ps1 new file mode 100644 index 000000000..23d8bfe6e --- /dev/null +++ b/Tests/Unit/MSFT_xWebVirtualDirectory.tests.ps1 @@ -0,0 +1,255 @@ +$DSCResourceName = 'MSFT_xWebVirtualDirectory' + +$Splat = @{ + Path = $PSScriptRoot + ChildPath = "..\..\DSCResources\$DSCResourceName\$DSCResourceName.psm1" + Resolve = $true + ErrorAction = 'Stop' +} +$DSCResourceModuleFile = Get-Item -Path (Join-Path @Splat) + +# should check for the server OS +if($env:APPVEYOR_BUILD_VERSION) +{ + Add-WindowsFeature Web-Server -Verbose +} + +if (Get-Module -Name $DSCResourceName) +{ + Remove-Module -Name $DSCResourceName +} + +Import-Module -Name $DSCResourceModuleFile.FullName -Force + +$moduleRoot = "${env:ProgramFiles}\WindowsPowerShell\Modules\xWebAdministration" + +if(-not (Test-Path -Path $moduleRoot)) +{ + $null = New-Item -Path $moduleRoot -ItemType Directory +} + +Copy-Item -Path $PSScriptRoot\..\..\* -Destination $moduleRoot -Recurse -Force -Exclude '.git' + +InModuleScope $DSCResourceName { + Describe 'Test-TargetResource' { + $MockSite = @{ + Website = 'contoso.com' + WebApplication = 'contosoapp' + Name = 'shared_directory' + PhysicalPath = 'C:\inetpub\wwwroot\shared' + Ensure = 'Present' + } + $virtualDir = @{ + Name = 'shared_directory' + PhysicalPath = 'C:\inetpub\wwwroot\shared' + Count = 1 + } + Context 'WebAdminstration is not installed' { + It 'should throw an error if WebAdministration is not installed' { + Mock Get-Module -ModuleName $ModuleName { return $null } + { + Test-TargetResource -Website $MockSite.Website -WebApplication $MockSite.WebApplication -Name $MockSite.Name -PhysicalPath $MockSite.PhysicalPath -Ensure $MockSite.Ensure + } | Should Throw 'Please ensure that WebAdministration module is installed.' + } + } + Context 'Directory is Present and PhysicalPath is Correct' { + It 'should return true' { + Mock Get-WebVirtualDirectoryInternal { return $virtualDir } + Test-TargetResource -Website $MockSite.Website -WebApplication $MockSite.WebApplication -Name $MockSite.Name -PhysicalPath $MockSite.PhysicalPath -Ensure $MockSite.Ensure | Should Be $true + } + } + + Context 'Directory is Present and PhysicalPath is incorrect' { + It 'should return false' { + $virtualDir = @{ + Name = 'shared_directory' + PhysicalPath = 'C:\inetpub\wwwroot\shared_wrong' + Count = 1 + } + + Mock Get-WebVirtualDirectoryInternal { return $virtualDir } + Test-TargetResource -Website $MockSite.Website -WebApplication $MockSite.WebApplication -Name $MockSite.Name -PhysicalPath $MockSite.PhysicalPath -Ensure $MockSite.Ensure | Should Be $false + } + } + + Context 'Directory is Present and PhysicalPath is incorrect' { + It 'should return false' { + $virtualDir = @{ + Name = 'shared_directory' + PhysicalPath = 'C:\inetpub\wwwroot\shared_wrong' + Count = 1 + } + + Mock Get-WebVirtualDirectoryInternal { return $virtualDir } + Test-TargetResource -Website $MockSite.Website -WebApplication $MockSite.WebApplication -Name $MockSite.Name -PhysicalPath $MockSite.PhysicalPath -Ensure $MockSite.Ensure | Should Be $false + } + } + } + + Describe 'Get-TargetResource' { + Context 'Ensure = Absent and virtual directory does not exist' { + It 'should return the correct values' { + $returnSite = @{ + Name = 'SomeName' + Website = 'Website' + WebApplication = 'Application' + PhysicalPath = 'PhysicalPath' + Ensure = 'Absent' + } + Mock Test-Dependancies { return $null } + Mock Get-WebVirtualDirectoryInternal { return $null } + $result = Get-TargetResource -Website $returnSite.Website -WebApplication $returnSite.WebApplication -Name $returnSite.Name -PhysicalPath $returnSite.PhysicalPath + + $result.Name | Should Be $returnSite.Name + $result.Website | Should Be $returnSite.Website + $result.WebApplication | Should Be $returnSite.WebApplication + $result.PhysicalPath | Should Be '' + $result.Ensure | Should Be $returnSite.Ensure + } + } + Context 'Ensure = Present and Physical Path Exists' { + $returnSite = @{ + Name = 'SomeName' + Website = 'Website' + WebApplication = 'Application' + PhysicalPath = 'PhysicalPath' + Ensure = 'Present' + } + + $returnObj = @{ + 'Name' = $returnSite.Name + 'PhysicalPath' = $returnSite.PhysicalPath + 'Count' = 1 + } + + Mock Test-Dependancies { return $null } + Mock Get-WebVirtualDirectoryInternal { return $returnObj } + $result = Get-TargetResource -Website $returnSite.Website -WebApplication $returnSite.WebApplication -Name $returnSite.Name -PhysicalPath $returnSite.PhysicalPath + + $result.Name | Should Be $returnSite.Name + $result.Website | Should Be $returnSite.Website + $result.WebApplication | Should Be $returnSite.WebApplication + $result.PhysicalPath | Should Be $returnSite.PhysicalPath + $result.Ensure | Should Be $returnSite.Ensure + } + } + + Describe 'Set-TargetResource' { + Context 'Ensure = Present and virtual directory does not exist' { + It 'should call New-WebVirtualDirectory' { + $mockSite = @{ + Name = 'SomeName' + Website = 'Website' + WebApplication = 'Application' + PhysicalPath = 'PhysicalPath' + } + + Mock Test-Dependancies { return $null } + Mock New-WebVirtualDirectory { return $null } + $null = Set-TargetResource -Website $mockSite.Website -WebApplication $mockSite.WebApplication -Name $mockSite.Name -PhysicalPath $mockSite.PhysicalPath -Ensure 'Present' + Assert-MockCalled New-WebVirtualDirectory -Exactly 1 + } + } + + Context 'Ensure = Present and virtual directory exists' { + It 'should call Set-ItemProperty' { + $mockSite = @{ + Name = 'SomeName' + Website = 'Website' + WebApplication = 'Application' + PhysicalPath = 'PhysicalPath' + Count = 1 + } + + Mock Test-Dependancies { return $null } + Mock Get-WebVirtualDirectoryInternal { return $mockSite } + Mock Set-ItemProperty { return $null } + $null = Set-TargetResource -Website $mockSite.Website -WebApplication $mockSite.WebApplication -Name $mockSite.Name -PhysicalPath $mockSite.PhysicalPath -Ensure 'Present' + Assert-MockCalled Set-ItemProperty -Exactly 1 + } + } + + Context 'Ensure = Absent' { + It 'should call Remove-WebVirtualDirectory' { + $mockSite = @{ + Name = 'SomeName' + Website = 'Website' + WebApplication = 'Application' + PhysicalPath = 'PhysicalPath' + Count = 1 + } + + Mock Test-Dependancies { return $null } + Mock Remove-WebVirtualDirectory { return $null } + $null = Set-TargetResource -Website $mockSite.Website -WebApplication $mockSite.WebApplication -Name $mockSite.Name -PhysicalPath $mockSite.PhysicalPath -Ensure 'Absent' + Assert-MockCalled Remove-WebVirtualDirectory -Exactly 1 + } + } + } + + Describe 'Get-WebVirtualDirectoryInternal' { + $MockSite = @{ + Website = 'contoso.com' + WebApplication = 'contosoapp' + Name = 'shared_directory' + PhysicalPath = 'C:\inetpub\wwwroot\shared' + Ensure = 'Present' + } + + Context 'Test-ApplicationExists returns false' { + Mock Test-ApplicationExists { return $false } + Mock Get-WebVirtualDirectory { return $Name } + It 'return the correct string' { + Get-WebVirtualDirectoryInternal -Name $MockSite.Name -Site $MockSite.Website -Application $MockSite.WebApplication | should be "$($MockSite.WebApplication)/$($MockSite.Name)" + } + } + + Context 'Test-ApplicationExists returns true' { + $returnObj = @{ + 'Name' = $MockSite.Name + 'Physical Path' = $MockSite.PhysicalPath + } + Mock Test-ApplicationExists { return $false } + Mock Get-WebVirtualDirectory { return $returnObj } + + It 'return the correct string' { + Get-WebVirtualDirectoryInternal -Name $MockSite.Name -Site $MockSite.Website -Application $MockSite.WebApplication | should be $returnObj + } + } + } + + Describe 'Test-ApplicationExists' { + $MockSite = @{ + Website = 'contoso.com' + WebApplication = 'contosoapp' + Name = 'shared_directory' + PhysicalPath = 'C:\inetpub\wwwroot\shared' + Ensure = 'Present' + } + + Context 'Get-WebApplication returns a value' { + It 'should return true' { + Mock Get-WebApplication { return @{Count = 1} } + Test-ApplicationExists -Site $MockSite.Website -Application $MockSite.WebApplication | should be $true + } + } + + Context 'Get-WebApplication returns no value' { + It 'should return false' { + Mock Get-WebApplication { return @{Count = 0} } + Test-ApplicationExists -Site $MockSite.Website -Application $MockSite.WebApplication | should be $false + } + } + } + + Describe 'Get-CompositeName' { + Context 'data is passed in' { + It 'should return the correct string' { + Get-CompositeName -Name 'Name' -Application 'Application' | should be 'Application/Name' + } + } + } +} + +# Cleanup after the test +Remove-Item -Path $moduleRoot -Recurse -Force diff --git a/Tests/Unit/MSFT_xWebsite.Tests.ps1 b/Tests/Unit/MSFT_xWebsite.Tests.ps1 new file mode 100644 index 000000000..131aa5fb4 --- /dev/null +++ b/Tests/Unit/MSFT_xWebsite.Tests.ps1 @@ -0,0 +1,1290 @@ +$DSCResourceName = 'MSFT_xWebsite' + +$Splat = @{ + Path = $PSScriptRoot + ChildPath = "..\..\DSCResources\$DSCResourceName\$DSCResourceName.psm1" + Resolve = $true + ErrorAction = 'Stop' +} +$DSCResourceModuleFile = Get-Item -Path (Join-Path @Splat) + +# should check for the server OS +if($env:APPVEYOR_BUILD_VERSION) +{ + Add-WindowsFeature Web-Server -Verbose +} + +if (Get-Module -Name $DSCResourceName) +{ + Remove-Module -Name $DSCResourceName +} + +Import-Module -Name $DSCResourceModuleFile.FullName -Force + +$moduleRoot = "${env:ProgramFiles}\WindowsPowerShell\Modules\xWebAdministration" + +if(-not (Test-Path -Path $moduleRoot)) +{ + $null = New-Item -Path $moduleRoot -ItemType Directory +} + +Copy-Item -Path $PSScriptRoot\..\..\* -Destination $moduleRoot -Recurse -Force -Exclude '.git' + +InModuleScope $DSCResourceName { + Describe "how Test-TargetResource to Ensure = 'Present'" { + $MockSite = @{ + Ensure = 'Present' + Name = 'MockName' + PhysicalPath = 'C:\NonExistant' + ID = 1 + State = 'MockState' + ApplicationPool = 'MockPool' + } + + Context 'WebAdminstration is not installed' { + It 'should throw an error if WebAdministration is not installed' { + Mock Get-Module -ModuleName $ModuleName { return $null } + { + Test-TargetResource -Name $MockSite.Name -Ensure $MockSite.Ensure -PhysicalPath $MockSite.PhysicalPath + } | Should Throw 'Please ensure that WebAdministration module is installed.' + } + } + + Context 'Check Ensure is false' { + It 'should return false' { + Mock Get-Website { + return $null + } + + $result = Test-TargetResource -Name $MockSite.Name -Ensure $MockSite.Ensure -PhysicalPath $MockSite.PhysicalPath -Verbose:$VerbosePreference + + $result | Should Be $false + } + } + + Context 'Check Physical Property is false' { + Mock Get-Website { + return $MockSite + } + Mock Test-WebsitePath -ModuleName $ModuleName { + return $true + } + + $result = Test-TargetResource -Name $MockSite.Name -Ensure $MockSite.Ensure -PhysicalPath $MockSite.PhysicalPath -Verbose:$VerbosePreference + + It 'should return false' { + $result | Should Be $false + } + } + + Context 'Check State is false' { + Mock Get-Website { + return $MockSite + } + Mock Test-WebsitePath -ModuleName $ModuleName { + return $false + } + + $result = Test-TargetResource -Name $MockSite.Name -Ensure $MockSite.Ensure -PhysicalPath $MockSite.PhysicalPath -State 'Started' -Verbose:$VerbosePreference + + It 'should return false' { + $result | Should Be $false + } + } + + Context 'Check Application Pool is false' { + $MockSite = @{ + Ensure = 'Present' + Name = 'MockName' + PhysicalPath = 'C:\NonExistant' + ID = 1 + State = 'Started' + ApplicationPool = 'MockPool' + } + + Mock Get-Website { + return $MockSite + } + Mock Test-WebsitePath -ModuleName $ModuleName { + return $false + } + + $result = Test-TargetResource -Name $MockSite.Name -Ensure $MockSite.Ensure -PhysicalPath $MockSite.PhysicalPath -State 'Started' -ApplicationPool 'MockPool2' -Verbose:$VerbosePreference + + It 'should return false' { + $result | Should Be $false + } + } + + Context 'Binding Properties is false' { + $MockSite = @{ + Ensure = 'Present' + Name = 'MockName' + PhysicalPath = 'C:\NonExistant' + ID = 1 + State = 'Started' + ApplicationPool = 'MockPool' + } + + $BindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '' + CertificateStoreName = '' + } + + $MockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ + Port = [System.UInt16] $BindingObject.Port + Protocol = $BindingObject.Protocol + IPAddress = $BindingObject.IPaddress + HostName = $BindingObject.Hostname + } -ClientOnly + + + Mock Get-Website { + return $MockSite + } + Mock Test-WebsitePath -ModuleName $ModuleName { + return $true + } + Mock Test-WebsiteBindings -ModuleName $ModuleName -Name $Name -BindingInfo $BindingInfo { + return $false + } + + $result = Test-TargetResource -Name $MockSite.Name -Ensure $MockSite.Ensure -PhysicalPath $MockSite.PhysicalPath -State 'Started' -ApplicationPool 'MockPool' -BindingInfo $MockBinding -Verbose:$VerbosePreference + + It 'should return false' { + $result | Should Be $false + } + } + + Context 'Default Page is false' { + $MockSite = @{ + Ensure = 'Present' + Name = 'MockName' + PhysicalPath = 'C:\NonExistant' + ID = 1 + State = 'Started' + ApplicationPool = 'MockPool' + DefaultPage = 'something' + } + + $BindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '' + CertificateStoreName = '' + } + + $MockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ + Port = [System.UInt16] $BindingObject.Port + Protocol = $BindingObject.Protocol + IPAddress = $BindingObject.IPaddress + HostName = $BindingObject.Hostname + } -ClientOnly + + + Mock Get-Website { + return $MockSite + } + + Mock Test-WebsitePath { + return $true + } + + Mock Test-WebsiteBindings -Name $Name -BindingInfo $BindingInfo { + return $true + } + + Mock Get-WebConfiguration { + return 'Notsomething' + } + + $result = Test-TargetResource -Name $MockSite.Name -Ensure $MockSite.Ensure -PhysicalPath $MockSite.PhysicalPath -State $MockSite.State -ApplicationPool $MockSite.ApplicationPool -BindingInfo $MockBinding -DefaultPage $MockSite.DefaultPage -Verbose:$VerbosePreference + + It 'should return false' { + $result | Should Be $false + } + } + } + + Describe "how Get-TargetResource responds to Ensure = 'Present'" { + $MockSite = @{ + Ensure = 'Present' + Name = 'MockName' + PhysicalPath = 'C:\NonExistant' + ID = 1 + State = 'Started' + ApplicationPool = 'MockPool' + } + + $BindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '' + CertificateStoreName = '' + } + + $MockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ + Port = [System.UInt16] $BindingObject.Port + Protocol = $BindingObject.Protocol + IPAddress = $BindingObject.IPaddress + HostName = $BindingObject.Hostname + } -ClientOnly + + Context 'WebAdminstration is not installed' { + It 'should throw an error if WebAdministration is not installed' { + Mock Get-Module -ModuleName $ModuleName { return $null } + { + Get-TargetResource -Name $MockSite.Name -PhysicalPath $MockSite.PhysicalPath + } | Should Throw 'Please ensure that WebAdministration module is installed.' + } + } + + Context 'No Website exists' { + Mock Get-Website { + return $null + } + $result = Get-TargetResource -Name 'MockName' -PhysicalPath $MockSite.PhysicalPath + + It 'should return absent' { + $result.Ensure | Should Be 'Absent' + } + } + + Context 'Multiple Websites of the same name exist' { + Mock Get-Website -ModuleName 'MSFT_xWebsite' { + return @( + [PSCustomObject] @{ + Name = 'Site1' + }, + [PSCustomObject] @{ + Name = 'Site1' + } + ) + } + + $errorId = 'WebsiteDiscoveryFailure,Get-TargetResource' + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult + $errorMessage = $($LocalizedData.WebsiteDiscoveryFailureError) -f 'Site1' + $exception = New-Object System.InvalidOperationException $errorMessage + $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null + + It 'should throw "WebsiteDiscoveryFailure"' { + { Get-TargetResource -Name 'Site1' -PhysicalPath 'C:\somePath' } | Should Throw $errorRecord + } + } + + Context 'Single website exists' { + $BindingObject = [PSCustomObject] @{ + Protocol = 'https' + IPAddress = '127.0.0.1' + Port = 443 + HostName = 'MockHostName' + } + + $BindingInfo = [PSCustomObject] @{ + bindingInformation = '127.0.0.1:443:MockHostName' + protocol = 'https' + SslFlags = 1 + CertificateHash = '3E09CCC8DFDCB8E3D4A83CFF164CC4754C25E9E5' + CertificateStoreName = 'My' + } + + $Website = [PSCustomObject] @{ + Name = 'MockHostName' + PhysicalPath = 'C:\SomePath' + State = 'Started' + ID = 0 + ApplicationPool = 'Pool' + Count = 1 + } + + Mock Get-Website { + return $Website + } + + Mock Get-ItemProperty { + return @{ + collection = $BindingInfo + } + } + + Mock Get-WebConfiguration { + return $null + } + + It 'should not throw' { + { + Get-TargetResource -Name 'MockHostName' -PhysicalPath 'C:\somePath' + } | Should Not throw + } + + $result = Get-TargetResource -Name 'MockHostName' -PhysicalPath 'C:\somePath' + + It 'should call Get-Website once' { + Assert-MockCalled -commandName Get-Website + } + + It 'should call Get-itemProperty once' { + Assert-MockCalled -commandName Get-ItemProperty + } + + It 'should return the name' { + $result.Name | Should Be 'MockHostName' + } + + It 'should return the EnsureResult' { + $result.Ensure | Should Be 'Present' + } + + It 'should return the PhysicalPath' { + $result.PhysicalPath | Should Be 'C:\SomePath' + } + + It 'should return the correct bindings' { + $result.BindingInfo.Port | Should Be $BindingObject.Port + $result.BindingInfo.Protocol | Should Be $BindingInfo.Protocol + $result.BindingInfo.IPAddress | Should Be $BindingObject.IPAddress + $result.BindingInfo.HostName | Should Be $BindingObject.HostName + $result.BindingInfo.CertificateThumbprint | Should Be $BindingInfo.Certificatehash + $result.BindingInfo.CertificateStoreName | Should Be $BindingInfo.CertificateStoreName + $result.BindingInfo.SSLFlags | Should Be $BindingInfo.SSLFlags + } + + It 'should return the State' { + $result.State | Should Be 'Started' + } + + It 'should return the ID' { + $result.ID | Should Be 0 + } + } + } + + Describe "how Set-TargetResource responds to Ensure = 'Present'" { + $MockSite = @{ + Ensure = 'Present' + Name = 'MockName' + PhysicalPath = 'C:\NonExistant' + ID = 1 + State = 'Stopped' + ApplicationPool = 'MockPool' + DefaultPage = 'index.htm' + } + + $BindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '' + CertificateStoreName = '' + } + + $MockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ + Port = [System.UInt16] $BindingObject.Port + Protocol = $BindingObject.Protocol + IPAddress = $BindingObject.IPaddress + HostName = $BindingObject.Hostname + } -ClientOnly + + + $MockSite2 = @{ + Ensure = 'Present' + Name = 'MockName2' + PhysicalPath = 'C:\NonExistant2' + ID = 1 + State = 'Stopped' + ApplicationPool = 'MockPool2' + DefaultPage = 'index.htm' + BindingInfo = $MockBinding + } + + Context 'Everything needs to be updated and application is started' { + Mock Get-Website { + return @($MockSite, $MockSite2) + } + Mock Start-Website {return $null} + + Mock Test-WebsitePath { return $true } + Mock Set-ItemProperty { return $null } + Mock Test-WebsiteBindings { return $true } + Mock Update-WebsiteBinding { return $null } + Mock Update-DefaultPages { return $null } + Mock Confirm-PortIPHostisUnique { return $true } + Mock Get-TargetResource { return $MockSite2 } + + $result = Set-TargetResource -Ensure 'Present' -Name $MockSite.Name -PhysicalPath $MockSite.PhysicalPath -State 'Started' -ApplicationPool 'MockPool2' -BindingInfo $MockBinding -DefaultPage $MockSite.DefaultPage + + It 'should call all the mocks' { + Assert-MockCalled Test-WebsitePath + Assert-MockCalled Set-ItemProperty 2 + Assert-MockCalled Update-WebsiteBinding + Assert-MockCalled Update-DefaultPages + Assert-MockCalled Confirm-PortIPHostisUnique + Assert-MockCalled Get-TargetResource + Assert-MockCalled Start-Website + } + } + + Context 'Confirm-PortIPHostisUnique returns false' { + Mock Get-Website { return @($MockSite, $MockSite2) } + Mock Start-Website {return $null} + Mock Test-WebsitePath { return $true } + Mock Set-ItemProperty { return $null } + Mock Test-WebsiteBindings { return $true } + Mock Update-WebsiteBinding { return $null } + Mock Update-DefaultPages { return $null } + Mock Confirm-PortIPHostisUnique { return $false } + Mock Get-TargetResource { return $MockSite2 } + + It 'should throw the right error' { + $errorId = 'WebsiteBindingConflictOnStart' + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult + $errorMessage = $($LocalizedData.WebsiteBindingConflictOnStartError) -f $MockSite.Name + $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage + $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null + + { Set-TargetResource -Ensure 'Present' -Name $MockSite.Name -PhysicalPath $MockSite.PhysicalPath -State 'Started' -ApplicationPool 'MockPool2' -BindingInfo $MockBinding -DefaultPage $MockSite.DefaultPage } | should throw $errorRecord + } + } + + Context 'Start-Website throws an error' { + Mock Get-Website { + return @($MockSite, $MockSite2) + } + Mock Start-Website {return throw} + + Mock Test-WebsitePath { return $true } + Mock Set-ItemProperty { return $null } + Mock Test-WebsiteBindings { return $true } + Mock Update-WebsiteBinding { return $null } + Mock Update-DefaultPages { return $null } + Mock Confirm-PortIPHostisUnique { return $true } + Mock Get-TargetResource { return $MockSite2 } + + It 'Should throw the correct error' { + + $errorId = 'WebsiteStateFailure' + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation + $errorMessage = $($LocalizedData.WebsiteStateFailureError) -f $MockSite.Name + $errorMessage += $_.Exception.Message + $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage + $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null + + { Set-TargetResource -Ensure 'Present' -Name $MockSite.Name -PhysicalPath $MockSite.PhysicalPath -State 'Started' -ApplicationPool 'MockPool2' -BindingInfo $MockBinding -DefaultPage $MockSite.DefaultPage } | should throw $errorRecord + } + } + + Context 'Everything needs to be updated and application is stopped' { + $MockSite = @{ + Ensure = 'Present' + Name = 'MockName' + PhysicalPath = 'C:\NonExistant' + ID = 1 + State = 'Started' + ApplicationPool = 'MockPool' + DefaultPage = 'index.htm' + } + + Mock Get-Website { + return @($MockSite, $MockSite2) + } + Mock Stop-Website {return $null} + + Mock Test-WebsitePath { return $true } + Mock Set-ItemProperty { return $null } + Mock Test-WebsiteBindings { return $true } + Mock Update-WebsiteBinding { return $null } + Mock Update-DefaultPages { return $null } + Mock Confirm-PortIPHostisUnique { return $true } + + $result = Set-TargetResource -Ensure 'Present' -Name $MockSite.Name -PhysicalPath $MockSite.PhysicalPath -State 'Stopped' -ApplicationPool 'MockPool2' -BindingInfo $MockBinding -DefaultPage $MockSite.DefaultPage + + It 'should call all the mocks' { + Assert-MockCalled Test-WebsitePath + Assert-MockCalled Set-ItemProperty 2 + Assert-MockCalled Update-WebsiteBinding + Assert-MockCalled Update-DefaultPages + Assert-MockCalled Stop-Website + } + } + + Context 'Website does not exist' { + $MockSite = @{ + Ensure = 'Present' + Name = 'MockName' + PhysicalPath = 'C:\NonExistant' + ID = 1 + State = 'Started' + ApplicationPool = 'MockPool' + DefaultPage = 'index.htm' + } + + Mock Get-Website { + return $MockSite + } + + Mock New-Website { return $null } + Mock Stop-Website { return $null } + Mock Test-WebsiteBindings { return $true } + Mock Update-WebsiteBinding { return $null } + Mock Update-DefaultPages { return $null } + Mock Start-Website { return $true } + Mock Get-ItemProperty { return $null } + + $result = Set-TargetResource -Ensure 'Present' -Name 'MockName2' -PhysicalPath $MockSite.PhysicalPath -State 'Started' -ApplicationPool 'MockPool2' -BindingInfo $MockBinding -DefaultPage $MockSite.DefaultPage + + It 'should call all the mocks' { + Assert-MockCalled New-Website + Assert-MockCalled Stop-Website + Assert-MockCalled Test-WebsiteBindings + Assert-MockCalled Update-WebsiteBinding + Assert-MockCalled Update-DefaultPages + Assert-MockCalled Start-Website + } + } + + Context 'Error in non-existant site' { + Mock New-Website {throw;} + It 'Should throw the correct error' { + $errorId = 'WebsiteCreationFailure' + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation + $errorMessage = $($LocalizedData.WebsiteCreationFailureError) -f 'MockName2' + $errorMessage += $_.Exception.Message + $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage + $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null + + {$result = Set-TargetResource -Ensure 'Present' -Name 'MockName2' -PhysicalPath $MockSite.PhysicalPath -State 'Started' -ApplicationPool 'MockPool2' -BindingInfo $MockBinding -DefaultPage $MockSite.DefaultPage } | Should throw $errorRecord + } + } + } + + Describe "how Set-TargetResource responds to Ensure = 'Absent'" { + It 'should call Remove-Website' { + $MockSite = @{ + Ensure = 'Present' + Name = 'MockName' + PhysicalPath = 'C:\NonExistant' + ID = 1 + State = 'Stopped' + ApplicationPool = 'MockPool' + DefaultPage = 'index.htm' + } + + $BindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '' + CertificateStoreName = '' + } + + $MockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ + Port = [System.UInt16] $BindingObject.Port + Protocol = $BindingObject.Protocol + IPAddress = $BindingObject.IPaddress + HostName = $BindingObject.Hostname + } -ClientOnly + + Mock Get-Website {return $MockSite} + Mock Remove-Website {return $null} + + $result = Set-TargetResource -Ensure 'Absent' -Name $MockSite.Name -PhysicalPath $MockSite.PhysicalPath -State 'Started' -ApplicationPool 'MockPool2' -BindingInfo $MockBinding -DefaultPage $MockSite.DefaultPage + + Assert-MockCalled Get-Website + Assert-MockCalled Remove-Website + } + + It 'should throw the right error' { + $MockSite = @{ + Ensure = 'Present' + Name = 'MockName' + PhysicalPath = 'C:\NonExistant' + ID = 1 + State = 'Stopped' + ApplicationPool = 'MockPool' + DefaultPage = 'index.htm' + } + + $BindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '' + CertificateStoreName = '' + } + + $MockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ + Port = [System.UInt16] $BindingObject.Port + Protocol = $BindingObject.Protocol + IPAddress = $BindingObject.IPaddress + HostName = $BindingObject.Hostname + } -ClientOnly + + Mock Get-Website {return $MockSite} + Mock Remove-Website {throw } + + $errorId = 'WebsiteRemovalFailure' + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation + $errorMessage = $($LocalizedData.WebsiteRemovalFailureError) -f $MockSite.Name + $errorMessage += $_.Exception.Message + $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage + $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null + + { Set-TargetResource -Ensure 'Absent' -Name $MockSite.Name -PhysicalPath $MockSite.PhysicalPath -State 'Started' -ApplicationPool 'MockPool2' -BindingInfo $MockBinding -DefaultPage $MockSite.DefaultPage } | should throw $errorRecord + } + } + + Describe 'how Get-WebBindingObject responds' { + Context 'IPv6 address is passed and the protocol is http' { + $BindingInfo = [PSCustomObject] @{ + bindingInformation = '[0:0:0:0:0:0:0:1]:80:MockHostName' + protocol = 'http' + } + + $result = Get-WebBindingObject -BindingInfo $BindingInfo + + It 'should return the IPv6 address' { + $result.IPaddress | Should be '0:0:0:0:0:0:0:1' + } + + It 'should return http' { + $result.Protocol | Should Be 'http' + } + + It 'should return the hostname' { + $result.Hostname | Should Be 'MockHostName' + } + + It 'should return the port' { + $result.Port | Should Be '80' + } + } + + Context 'IPv4 address is passed and the protocol is http' { + $BindingInfo = [PSCustomObject] @{ + bindingInformation = '127.0.0.1:80:MockHostName' + protocol = 'http' + } + + $result = Get-WebBindingObject -BindingInfo $BindingInfo + + It 'should return the IPv6 address' { + $result.IPaddress | Should be '127.0.0.1' + } + + It 'should return http' { + $result.Protocol | Should Be 'http' + } + + It 'should return the hostname' { + $result.Hostname | Should Be 'MockHostName' + } + + It 'should return the port' { + $result.Port | Should Be '80' + } + } + + Context 'IPv4 SSL Certificate is passed' { + $BindingInfo = [PSCustomObject] @{ + bindingInformation = '127.0.0.1:443:MockHostName' + protocol = 'https' + CertificateHash = '3E09CCC8DFDCB8E3D4A83CFF164CC4754C25E9E5' + CertificateStoreName = 'My' + SSLFlags = '1' + } + + $result = Get-WebBindingObject -BindingInfo $BindingInfo + + It 'should return the IPv6 address' { + $result.IPaddress | Should be '127.0.0.1' + } + + It 'should return http' { + $result.Protocol | Should Be 'https' + } + + It 'should return the hostname' { + $result.Hostname | Should Be 'MockHostName' + } + + It 'should return the port' { + $result.Port | Should Be '443' + } + + It 'should return the Hash' { + $result.CertificateThumbprint | Should Be '3E09CCC8DFDCB8E3D4A83CFF164CC4754C25E9E5' + } + + It 'should return the store' { + $result.CertificateStoreName | Should Be 'My' + } + + It 'should return the SSLFlags' { + $result.SSLFlags | Should Be '1' + } + } + + Context 'IPv6 SSL Certificate is passed' { + $BindingInfo = [PSCustomObject] @{ + bindingInformation = '[0:0:0:0:0:0:0:1]:443:MockHostName' + protocol = 'https' + CertificateHash = '3E09CCC8DFDCB8E3D4A83CFF164CC4754C25E9E5' + CertificateStoreName = 'My' + SSLFlags = '1' + } + + $result = Get-WebBindingObject -BindingInfo $BindingInfo + + It 'should return the IPv6 address' { + $result.IPaddress | Should be '0:0:0:0:0:0:0:1' + } + + It 'should return http' { + $result.Protocol | Should Be 'https' + } + + It 'should return the hostname' { + $result.Hostname | Should Be 'MockHostName' + } + + It 'should return the port' { + $result.Port | Should Be '443' + } + + It 'should return the Hash' { + $result.CertificateThumbprint | Should Be '3E09CCC8DFDCB8E3D4A83CFF164CC4754C25E9E5' + } + + It 'should return the store' { + $result.CertificateStoreName | Should Be 'My' + } + + It 'should return the SSLFlags' { + $result.SSLFlags | Should Be '1' + } + } + } + + Describe 'Test-WebsitePath' { + Context 'the path is wrong' { + It 'Should return true' { + Mock Get-ItemProperty { + return 'C:\WrongPath' + } + Test-WebsitePath -Name 'SomeSite' -PhysicalPath 'C:\RightPath' | Should be $true + } + } + + Context 'the path is correct' { + It 'Should return false if the path does not need to be updated' { + Mock Get-ItemProperty { + return 'C:\RightPath' + } + Test-WebsitePath -Name 'SomeSite' -PhysicalPath 'C:\RightPath' | Should be $false + } + } + } + + Describe 'Confirm-PortIPHostisUnique' { + Context 'bindings are not unique' { + It 'should return false' { + $BindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '' + CertificateStoreName = '' + } + + $bindingArray = @() + $mockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ + Port = [System.UInt16] $BindingObject.Port + Protocol = $BindingObject.Protocol + IPAddress = $BindingObject.IPaddress + HostName = $BindingObject.Hostname + } -ClientOnly + + $bindingArray += $MockBinding, $MockBinding + + Confirm-PortIPHostisUnique -Port $BindingObject.Port -IPAddress $BindingObject.IPAddress -HostName $BindingObject.Hostname -BindingInfo $bindingArray | should be $false + } + } + + Context 'bindings are unique' { + It 'should return true' { + $BindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '' + CertificateStoreName = '' + } + + $mockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ + Port = [System.UInt16] $BindingObject.Port + Protocol = $BindingObject.Protocol + IPAddress = $BindingObject.IPaddress + HostName = $BindingObject.Hostname + } -ClientOnly + + $bindingArray = $MockBinding + + Confirm-PortIPHostisUnique -Port $BindingObject.Port -IPAddress $BindingObject.IPAddress -HostName $BindingObject.Hostname -BindingInfo $bindingArray | should be $true + } + } + } + + Describe 'Test-WebsiteBindings' { + $MockSite = @{ + Ensure = 'Present' + Name = 'MockHostName' + PhysicalPath = 'C:\NonExistant' + ID = 1 + State = 'Started' + ApplicationPool = 'MockPool' + BindingInformation = '127.0.0.1:80:' + } + + $BindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '' + CertificateStoreName = '' + SSLFlags = 0 + } + + $mockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ + Port = [System.UInt16] $BindingObject.Port + Protocol = $BindingObject.Protocol + IPAddress = $BindingObject.IPaddress + HostName = $BindingObject.Hostname + SSLFlags = $BindingObject.SSLFlags + } -ClientOnly + + Context 'Confirm-PortIPHostisUnique returns false' { + It 'should throw an error' { + Mock Confirm-PortIPHostisUnique {return $false} + + $errorId = 'WebsiteBindingInputInvalidation' + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult + $errorMessage = $($LocalizedData.WebsiteBindingInputInvalidationError) -f $BindingObject.Hostname + $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage + $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null + + {Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $mockBinding } | Should throw $errorRecord + } + } + + Context 'Comparing bindings throws an error' { + + $badBindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '' + CertificateStoreName = '' + } + + Mock Confirm-PortIPHostisUnique {return $true} + Mock Get-WebBinding {return $BindingObject} + Mock Get-Website {return $MockSite} + Mock Get-WebBindingObject { return $MockBinding } + + $errorId = 'WebsiteCompareFailure' + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult + $errorMessage = $($LocalizedData.WebsiteCompareFailureError) -f $BindingObject.Hostname + $errorMessage += $_.Exception.Message + $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage + $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null + + It 'should return an error' { + {Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $badBindingObject } | Should not throw $errorRecord # currently broken + } + } + + Context 'Port is incorrect' { + $badBindingObject = @{ + Port = 81 + Protocol = 'http' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '' + CertificateStoreName = '' + } + + Mock Confirm-PortIPHostisUnique {return $true} + Mock Get-WebBinding {return $BindingObject} + Mock Get-Website {return $MockSite} + Mock Get-WebBindingObject { return $badBindingObject } + + It 'should return true' { + Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $MockBinding | Should be $true + } + } + + Context 'Protocol is incorrect' { + $badBindingObject = @{ + Port = 80 + Protocol = 'https' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '' + CertificateStoreName = '' + } + + Mock Confirm-PortIPHostisUnique {return $true} + Mock Get-WebBinding {return $BindingObject} + Mock Get-Website {return $MockSite} + Mock Get-WebBindingObject { return $badBindingObject } + + It 'should return true' { + Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $MockBinding | Should be $true + } + } + + Context 'IPAddress is incorrect' { + $badBindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '127.0.0.2' + HostName = 'MockHostName' + CertificateThumbprint = '' + CertificateStoreName = '' + } + + Mock Confirm-PortIPHostisUnique {return $true} + Mock Get-WebBinding {return $BindingObject} + Mock Get-Website {return $MockSite} + Mock Get-WebBindingObject { return $badBindingObject } + + It 'should return true' { + Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $MockBinding | Should be $true + } + } + + Context 'IPAddress is *' { + $BindingObjectIP = @{ + Port = 80 + Protocol = 'http' + IPAddress = '' + HostName = 'MockHostName' + CertificateThumbprint = '' + CertificateStoreName = '' + SSLFlags = 0 + } + + $mockBindingIP = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ + Port = [System.UInt16] $BindingObjectIP.Port + Protocol = $BindingObjectIP.Protocol + IPAddress = $BindingObjectIP.IPaddress + HostName = $BindingObjectIP.Hostname + } -ClientOnly + + $badBindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '*' + HostName = 'MockHostName' + CertificateThumbprint = '' + CertificateStoreName = '' + } + + Mock Confirm-PortIPHostisUnique {return $true} + Mock Get-WebBinding {return $BindingObjectIP } + Mock Get-Website {return $MockSite} + Mock Get-WebBindingObject { return $badBindingObject } + + It 'should return false' { + Test-WebsiteBindings -Name $BindingObjectIP.hostname -BindingInfo $mockBindingIP | Should be $false + } + } + + Context 'Hostname is incorrect' { + $badBindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '127.0.0.1' + HostName = 'MockHostName2' + CertificateThumbprint = '' + CertificateStoreName = '' + } + + Mock Confirm-PortIPHostisUnique {return $true} + Mock Get-WebBinding {return $BindingObject} + Mock Get-Website {return $MockSite} + Mock Get-WebBindingObject { return $badBindingObject } + + It 'should return true' { + Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $MockBinding | Should be $true + } + } + + Context 'CertificateThumbprint is incorrect' { + $badBindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '1234560215616' + CertificateStoreName = '' + } + + Mock Confirm-PortIPHostisUnique {return $true} + Mock Get-WebBinding {return $BindingObject} + Mock Get-Website {return $MockSite} + Mock Get-WebBindingObject { return $badBindingObject } + + It 'should return true' { + Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $MockBinding | Should be $true + } + } + + Context 'CertificateStoreName is incorrect' { + $badBindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '1234560215616' + CertificateStoreName = 'WebHosting' + } + + Mock Confirm-PortIPHostisUnique {return $true} + Mock Get-WebBinding {return $BindingObject} + Mock Get-Website {return $MockSite} + Mock Get-WebBindingObject { return $badBindingObject } + + It 'should return true' { + Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $MockBinding | Should be $true + } + } + + Context 'CertificateStoreName is incorrect and no thumbrpint is specified' { + $badBindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '' + CertificateStoreName = 'WebHosting' + SSLFlags = 0 + } + + Mock Confirm-PortIPHostisUnique {return $true} + Mock Get-WebBinding {return $BindingObject} + Mock Get-Website {return $MockSite} + Mock Get-WebBindingObject { return $badBindingObject } + + It 'should return false' { + Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $MockBinding | Should be $false + } + } + + Context 'SSLFlags is incorrect' { + $badBindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '' + CertificateStoreName = '' + SSLFlags = 1 + } + + Mock Confirm-PortIPHostisUnique {return $true} + Mock Get-WebBinding {return $BindingObject} + Mock Get-Website {return $MockSite} + Mock Get-WebBindingObject { return $badBindingObject } + + It 'should return true' { + Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $MockBinding | Should be $true + } + } + + Context 'Everything is the same' { + $badBindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '' + CertificateStoreName = '' + SSLFlags = 0 + } + + Mock Confirm-PortIPHostisUnique {return $true} + Mock Get-WebBinding {return $BindingObject} + Mock Get-Website {return $MockSite} + Mock Get-WebBindingObject { return $badBindingObject } + + It 'should return false' { + Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $MockBinding | Should be $false + } + } + } + + Describe 'Update-WebsiteBinding' { + $MockSite = @{ + Ensure = 'Present' + Name = 'MockHostName' + PhysicalPath = 'C:\NonExistant' + ID = 1 + State = 'Started' + ApplicationPool = 'MockPool' + BindingInformation = '127.0.0.1:443:' + } + + $BindingObject = @{ + Port = 443 + Protocol = 'https' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '1234561651481561891481654891651' + CertificateStoreName = 'MY' + SSLFlags = 1 + } + + $mockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ + Port = [System.UInt16] $BindingObject.Port + Protocol = $BindingObject.Protocol + IPAddress = $BindingObject.IPaddress + HostName = $BindingObject.Hostname + SSLFlags = $BindingObject.SSLFlags + } -ClientOnly + + Context 'expected behavior' { + Mock Clear-ItemProperty { return $null } + Mock New-WebBinding { return @{ + Name = $Name; + Protocol = $Protocol; + Port = $Port; + IPaddress = $IPaddress; + Hostheader = $Hostheader; + SslFlags = $SslFlags; + } + } -Verifiable + + $result = Update-WebsiteBinding -Name $MockSite.Name -BindingInfo $mockBinding + It 'should call all the mocks' { + Assert-MockCalled New-WebBinding + } + + It 'should use the right name' { + $result.Name | Should be $MockSite.Name + } + + It 'should use the right protocol' { + $result.Protocol | Should be $mockBinding.Protocol + } + + It 'should use the right IPaddress' { + $result.IPaddress | Should be $mockBinding.IPaddress + } + + It 'should use the right Hostheader' { + $result.Hostheader | Should be $mockBinding.HostName + } + + It 'should use the right SSLFlags' { + $result.SslFlags | Should be $mockBinding.SslFlags + } + } + + Context 'New-WebBinding throws an error' { + It 'should throw the right error' { + $errorId = 'WebsiteBindingUpdateFailure' + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult + $errorMessage = $($LocalizedData.WebsiteBindingUpdateFailureError) -f $MockSite.Name + $errorMessage += $_.Exception.Message + $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage + $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null + + Mock Clear-ItemProperty { return $null } + Mock New-WebBinding { throw} + + { Update-WebsiteBinding -Name $MockSite.Name -BindingInfo $mockBinding } | should throw $errorRecord + } + } + + Context 'Get-WebBinding throws an error' { + $MockSite = @{ + Ensure = 'Present' + Name = 'MockHostName' + PhysicalPath = 'C:\NonExistant' + ID = 1 + State = 'Started' + ApplicationPool = 'MockPool' + BindingInformation = '127.0.0.1:80:' + } + + $BindingObject = @{ + Port = 80 + Protocol = 'http' + IPAddress = '127.0.0.1' + HostName = 'MockHostName' + CertificateThumbprint = '1234561651481561891481654891651' + CertificateStoreName = 'MY' + } + + $mockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ + Port = [System.UInt16] $BindingObject.Port + Protocol = $BindingObject.Protocol + IPAddress = $BindingObject.IPaddress + HostName = $BindingObject.Hostname + CertificateThumbprint = $BindingObject.CertificateThumbprint + CertificateStoreName = $BindingObject.CertificateStoreName + } -ClientOnly + + It 'should throw the right error' { + $obj = New-Module -AsCustomObject -ScriptBlock { + function AddSslCertificate { + throw; + } + } + Mock Clear-ItemProperty { return $null } + Mock New-WebBinding { return $null } + Mock Get-WebBinding { return throw; } + + $errorId = 'WebBindingCertifcateError' + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation + $errorMessage = $($LocalizedData.WebBindingCertifcateError) -f $BindingObject.CertificateThumbprint + $errorMessage += $_.Exception.Message + $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage + $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null + + { Update-WebsiteBinding -Name $MockSite.Name -BindingInfo $mockBinding } | should throw $errorRecord + } + } + } + + Describe 'Update-DefaultPages' { + Context 'Does not find the default page' { + It 'should call Add-WebConfiguration' { + Mock Get-WebConfiguration { return 'index.htm' } + Mock Add-WebConfiguration { return $null } + $result = Update-DefaultPages -Name 'Default Web Site' -DefaultPage 'index2.htm' + Assert-MockCalled -commandName Add-WebConfiguration + } + } + } +} + +# Cleanup after the test +Remove-Item -Path $moduleRoot -Recurse -Force diff --git a/appveyor.yml b/appveyor.yml index 62d98c28f..f058033b4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,25 +1,64 @@ -install: - - cinst -y pester - - git clone https://github.com/PowerShell/DscResource.Tests +#---------------------------------# +# environment configuration # +#---------------------------------# +# This is necessary to use WMF5 +os: unstable +version: 1.7.{build}.0 +install: + - cinst -y pester + - git clone https://github.com/PowerShell/DscResource.Tests + - ps: Push-Location + - cd DscResource.Tests + - ps: Import-Module .\TestHelper.psm1 -force + - ps: Pop-Location + - ps: Get-PackageProvider -name nuget -ForceBootStrap -Force + +#---------------------------------# +# build configuration # +#---------------------------------# build: false +#---------------------------------# +# test configuration # +#---------------------------------# + test_script: - ps: | $testResultsFile = ".\TestsResults.xml" $res = Invoke-Pester -OutputFormat NUnitXml -OutputFile $testResultsFile -PassThru (New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path $testResultsFile)) - if ($res.FailedCount -gt 0) { + if ($res.FailedCount -gt 0) { throw "$($res.FailedCount) tests failed." } -on_finish: - - ps: | - $stagingDirectory = (Resolve-Path ..).Path - $zipFile = Join-Path $stagingDirectory "$(Split-Path $pwd -Leaf).zip" - Add-Type -assemblyname System.IO.Compression.FileSystem - [System.IO.Compression.ZipFile]::CreateFromDirectory($pwd, $zipFile) - @( - # You can add other artifacts here - (ls $zipFile) - ) | % { Push-AppveyorArtifact $_.FullName } + +#---------------------------------# +# deployment configuration # +#---------------------------------# + +# scripts to run before deployment +before_deploy: + - ps: | + # Creating project artifact + $stagingDirectory = (Resolve-Path ..).Path + $manifest = Join-Path $pwd "xWebAdministration.psd1" + (Get-Content $manifest -Raw).Replace("1.7.0.0", $env:APPVEYOR_BUILD_VERSION) | Out-File $manifest + $zipFilePath = Join-Path $stagingDirectory "$(Split-Path $pwd -Leaf).zip" + Add-Type -assemblyname System.IO.Compression.FileSystem + [System.IO.Compression.ZipFile]::CreateFromDirectory($pwd, $zipFilePath) + + # Creating NuGet package artifact + New-Nuspec -packageName $env:APPVEYOR_PROJECT_NAME -version $env:APPVEYOR_BUILD_VERSION -author "Microsoft" -owners "Microsoft" -licenseUrl "https://github.com/PowerShell/DscResources/blob/master/LICENSE" -projectUrl "https://github.com/$($env:APPVEYOR_REPO_NAME)" -packageDescription $env:APPVEYOR_PROJECT_NAME -tags "DesiredStateConfiguration DSC DSCResourceKit" -destinationPath . + nuget pack ".\$($env:APPVEYOR_PROJECT_NAME).nuspec" -outputdirectory . + $nuGetPackageName = $env:APPVEYOR_PROJECT_NAME + "." + $env:APPVEYOR_BUILD_VERSION + ".nupkg" + $nuGetPackagePath = (Get-ChildItem $nuGetPackageName).FullName + + @( + # You can add other artifacts here + $zipFilePath, + $nuGetPackagePath + ) | % { + Write-Host "Pushing package $_ as Appveyor artifact" + Push-AppveyorArtifact $_ + } diff --git a/xWebAdministration.psd1 b/xWebAdministration.psd1 index 1d5939b67..1b8a4dbf1 100644 --- a/xWebAdministration.psd1 +++ b/xWebAdministration.psd1 @@ -1,6 +1,6 @@ @{ # Version number of this module. -ModuleVersion = '1.3.2.4' +ModuleVersion = '1.7.0.0' # ID used to uniquely identify this module GUID = 'b3239f27-d7d3-4ae6-a5d2-d9a1c97d6ae4'