Tests/Integration/MSFT_xDSCWebService.Integration.tests.ps1
$script:dscModuleName = 'xPSDesiredStateConfiguration' $script:dscResourceFriendlyName = 'xDSCWebService' $script:dcsResourceName = "MSFT_$($script:dscResourceFriendlyName)" #region HEADER # Integration Test Template Version: 1.3.1 [System.String] $script:moduleRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) if ( (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests'))) -or ` (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1'))) ) { & git @('clone', 'https://github.com/PowerShell/DscResource.Tests.git', (Join-Path -Path $script:moduleRoot -ChildPath 'DscResource.Tests')) } # Ensure that Powershell Module 'WebAdministration' is available if (-not (Install-WindowsFeatureAndVerify -Name Web-Mgmt-Tools)) { throw 'Failed to verify for required Windows Feature. Unable to continue ...' } Import-Module -Name WebAdministration -ErrorAction:Stop -Force Import-Module -Name (Join-Path -Path $script:moduleRoot -ChildPath (Join-Path -Path 'DSCResource.Tests' -ChildPath 'TestHelper.psm1')) -ErrorAction:Stop -Force $TestEnvironment = Initialize-TestEnvironment ` -DSCModuleName $script:dscModuleName ` -DSCResourceName $script:dcsResourceName ` -TestType Integration Import-Module -Name (Join-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -ChildPath 'CommonTestHelper.psm1') -ErrorAction:Stop -Force if (Test-SkipContinuousIntegrationTask -Type 'Integration') { return } $configurationFile = Join-Path -Path $PSScriptRoot -ChildPath "$($script:dcsResourceName).config.ps1" if ($env:CI -eq $false) { # Install modules $requiredModules = Get-ResourceModulesInConfiguration -ConfigurationPath $configurationFile | Where-Object -Property Name -ne $script:dscModuleName if ($requiredModules) { Install-DependentModule -Module $requiredModules } } <# .SYNOPSIS Performs common DSC integration tests including compiling, setting, testing, and getting a configuration. .PARAMETER ConfigurationName The name of the configuration being executed. #> function Invoke-CommonResourceTesting { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $ConfigurationName ) It 'Should compile and apply the MOF without throwing' { { $configurationParameters = @{ OutputPath = $TestDrive ConfigurationData = $ConfigurationData } & $configurationName @configurationParameters $startDscConfigurationParameters = @{ Path = $TestDrive ComputerName = 'localhost' Wait = $true Force = $true ErrorAction = 'Stop' } Start-DscConfiguration @startDscConfigurationParameters } | Should -Not -Throw } It 'Should be able to call Get-DscConfiguration without throwing' { { $script:currentConfiguration = Get-DscConfiguration -ErrorAction Stop } | Should -Not -Throw } It 'Should return $true when Test-DscConfiguration is run' { Test-DscConfiguration | Should -Be $true } } <# .SYNOPSIS Tests if the specified IIS application pool is absent or present .PARAMETER ApplicationPoolName name of the IIS application pool .PARAMETER ResourceState state of the IIS application pool #> function Test-IISApplicationPool { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $ApplicationPoolName, [Parameter(Mandatory = $true)] [ValidateSet('Present', 'Absent')] [System.String] $ResourceState ) $appPoolPath = Join-Path -Path 'IIS:\AppPools' -ChildPath $ApplicationPoolName switch ($ResourceState) { 'Present' { Test-Path -Path $appPoolPath } 'Absent' { -not (Test-Path -Path $appPoolPath) } } } <# .SYNOPSIS Performs common tests to ensure that the DSC pull server was properly installed. .PARAMETER WebsiteName name of the Pull Server website .PARAMETER ResourceState state of the resource (website) .PARAMETER WebsiteState State of the website .PARAMETER ApplicationPoolName name of the IIS application pool #> function Test-DSCPullServer { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $WebsiteName, [Parameter(Mandatory = $true)] [ValidateSet('Present', 'Absent')] [System.String] $ResourceState, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $WebsiteState, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $ApplicationPoolName = 'PSWS' ) switch ($ResourceState) { 'Present' { It 'Should create a web.config file at the web site root' { Test-Path -Path (Join-Path -Path $ConfigurationData.AllNodes.PhysicalPath -ChildPath 'web.config') | Should -Be $true } It ("Should exist a WebSite called $WebsiteName") { Get-WebSite -Name $WebsiteName | Should Not Be $null } It ("WebSite $WebsiteName should be started") { $website = Get-WebSite -Name $WebsiteName $website | Should Not Be $null $website.state | Should BeExactly $WebsiteState } It "IIS Application pool $ApplicationPoolName should exist" { Test-IISApplicationPool -ApplicationPoolName $ApplicationPoolName -ResourceState 'Present' | Should -Be $true } It "WebSite $WebsiteName should be bound to IIS applicaiton pool $ApplicationPoolName" { $website = Get-WebSite -Name $WebsiteName $website | Should Not Be $null $website.applicationPool | Should BeExactly $ApplicationPoolName } } 'Absent' { It ("Should not exist a WebSite called $WebsiteName") { Get-WebSite -Name $WebsiteName | Should Be $null } } } } <# .SYNOPSIS Performs a test on defined firewall rules .PARAMETER RuleName name of the firewall rule .PARAMETER ResourceState state of the rule #> function Test-DSCPullServerFirewallRule { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $RuleName, [Parameter(Mandatory = $true)] [ValidateSet('Present', 'Absent')] [System.String] $ResourceState ) Write-Verbose -Message "Test-DSCPullServerFirewallRule $RuleName for state $ResourceState." $expectedRuleCount = 0 if ('Present' -eq $ResourceState) { $expectedRuleCount = 1 } It ("Should $(if ('Present' -eq $ResourceState) { '' } else { 'not ' })create a firewall rule $RuleName for the chosen port") { $ruleCnt = (Get-NetFirewallRule | Where-Object -FilterScript { $_.DisplayName -eq $RuleName #'DSCPullServer_IIS_Port' } | Measure-Object).Count Write-Verbose -Message "Found $ruleCnt firewall rules with name '$RuleName'" $ruleCnt | Should -Be $expectedRuleCount } } #endregion # Using try/finally to always cleanup. try { # Get a self signed certificate to use with tests New-DscSelfSignedCertificate if (!(Test-Path -Path env:DscPublicCertificatePath) -or ` !(Test-Path -Path env:DscCertificateThumbprint)) { throw "A DSC certificate is required for $script:dscResourceFriendlyName integration tests." } # Make sure the DSC-Service and Web-Server Windows features are installed if (!(Install-WindowsFeatureAndVerify -Name 'DSC-Service') -or !(Install-WindowsFeatureAndVerify -Name 'Web-Server')) { Write-Verbose -Message 'Skipping xDSCWebService Integration tests due to missing Windows Features.' -Verbose return } # Make sure the w3svc is running before proceeding with tests Start-Service -Name w3svc -ErrorAction Stop #region Integration Tests . $configurationFile Describe "$($script:dcsResourceName)_Integration" { $ensureAbsentConfigurationName = 'MSFT_xDSCWebService_PullTestRemoval_Config' $ensurePresentConfigurationNames = @( 'MSFT_xDSCWebService_PullTestWithSecurityBestPractices_Config', 'MSFT_xDSCWebService_PullTestWithoutSecurityBestPractices_Config' ) foreach ($configurationName in $ensurePresentConfigurationNames) { Context ('When using configuration {0}' -f $configurationName) { BeforeAll { Invoke-CommonResourceTesting -ConfigurationName $ensureAbsentConfigurationName } AfterAll { Invoke-CommonResourceTesting -ConfigurationName $ensureAbsentConfigurationName } Invoke-CommonResourceTesting -ConfigurationName $configurationName Test-DSCPullServer -WebsiteName 'PSDSCPullServer' -ResourceState 'Present' -WebsiteState 'Started' Test-DSCPullServerFirewallRule -RuleName 'DSCPullServer_IIS_Port' -ResourceState 'Present' } } Context 'Verify clean removal' { BeforeAll { Invoke-CommonResourceTesting -ConfigurationName $ensureAbsentConfigurationName } Invoke-CommonResourceTesting -ConfigurationName 'MSFT_xDSCWebService_PullTestWithSecurityBestPractices_Config' Test-DSCPullServer -WebsiteName 'PSDSCPullServer' -ResourceState 'Present' -WebsiteState 'Started' Test-DSCPullServerFirewallRule -RuleName 'DSCPullServer_IIS_Port' -ResourceState 'Present' Invoke-CommonResourceTesting -ConfigurationName $ensureAbsentConfigurationName Test-DSCPullServer -WebsiteName 'PSDSCPullServer' -ResourceState 'Absent' -WebsiteState 'Absent' Test-DSCPullServerFirewallRule -RuleName 'DSCPullServer_IIS_Port' -ResourceState 'Absent' } Context 'No firewall configuration' { $configurationName = 'MSFT_xDSCWebService_PullTestWithoutFirewall_Config' BeforeAll { Invoke-CommonResourceTesting -ConfigurationName $ensureAbsentConfigurationName } AfterAll { Invoke-CommonResourceTesting -ConfigurationName $ensureAbsentConfigurationName } Invoke-CommonResourceTesting -ConfigurationName $configurationName Test-DSCPullServer -WebsiteName 'PSDSCPullServer' -ResourceState 'Present' -WebsiteState 'Started' Test-DSCPullServerFirewallRule -RuleName 'DSCPullServer_IIS_Port' -ResourceState 'Absent' } Context 'Separate firewall role definition' { BeforeAll { Invoke-CommonResourceTesting -ConfigurationName $ensureAbsentConfigurationName } Invoke-CommonResourceTesting -ConfigurationName 'MSFT_xDSCWebService_PullTestWithSeparateFirewallRule_Config' Test-DSCPullServer -WebsiteName 'PSDSCPullServer' -ResourceState 'Present' -WebsiteState 'Started' Test-DSCPullServerFirewallRule -RuleName 'DSCPullServer_IIS_Port' -ResourceState 'Absent' Test-DSCPullServerFirewallRule -RuleName 'DSC PullServer 8080' -ResourceState 'Present' Invoke-CommonResourceTesting -ConfigurationName $ensureAbsentConfigurationName Test-DSCPullServer -WebsiteName 'PSDSCPullServer' -ResourceState 'Absent' -WebsiteState 'Absent' Test-DSCPullServerFirewallRule -RuleName 'DSCPullServer_IIS_Port' -ResourceState 'Absent' Test-DSCPullServerFirewallRule -RuleName 'DSC PullServer 8080' -ResourceState 'Present' } Context 'Separate IIS application pool definition' { BeforeAll { Invoke-CommonResourceTesting -ConfigurationName $ensureAbsentConfigurationName } Invoke-CommonResourceTesting -ConfigurationName 'MSFT_xDSCWebService_PullTestSeparateAppPool_Config' Test-DSCPullServer -WebsiteName 'PSDSCPullServer' -ResourceState 'Present' -WebsiteState 'Started' -ApplicationPoolName 'PSDSCPullServer_PSDSCPullServer' Test-DSCPullServerFirewallRule -RuleName 'DSCPullServer_IIS_Port' -ResourceState 'Absent' Invoke-CommonResourceTesting -ConfigurationName $ensureAbsentConfigurationName Test-DSCPullServer -WebsiteName 'PSDSCPullServer' -ResourceState 'Absent' -WebsiteState 'Absent' Test-DSCPullServerFirewallRule -RuleName 'DSCPullServer_IIS_Port' -ResourceState 'Absent' It "Separately created IIS Application pool should still exist after cleanup" { Test-IISApplicationPool -ApplicationPoolName 'PSDSCPullServer_PSDSCPullServer' -ResourceState 'Present' | Should -Be $true } } } #endregion } finally { #region FOOTER Restore-TestEnvironment -TestEnvironment $TestEnvironment #endregion } |