From 139cbb268fa6226b7054c9917241582e13070a14 Mon Sep 17 00:00:00 2001 From: Yorick Kuijs Date: Tue, 28 Sep 2021 13:15:14 +0200 Subject: [PATCH 1/2] Fixes #1346, #1347, #1348 and #1349 --- CHANGELOG.md | 26 ++ .../MSFT_SPDocIcon/MSFT_SPDocIcon.psm1 | 10 +- .../MSFT_SPHealthAnalyzerRuleState.schema.mof | 16 - .../MSFT_SPLogLevel/MSFT_SPLogLevel.psm1 | 162 +++++--- .../MSFT_SPSearchServiceApp.psm1 | 36 +- .../MSFT_SPServiceAppPool.psm1 | 2 +- .../DSCResources/MSFT_SPSite/MSFT_SPSite.psm1 | 20 +- .../MSFT_SPWebApplication.psm1 | 113 +++++- .../SharePointDsc.Reverse.psm1 | 22 +- .../SPSearchServiceApp.psm1 | 6 +- .../SharePointDsc.Util.psm1 | 3 +- .../SharePointDsc.SPDocIcon.Tests.ps1 | 26 +- .../SharePointDsc.SPLogLevel.Tests.ps1 | 366 ++++++++++++------ .../SharePointDsc.SPServiceAppPool.Tests.ps1 | 4 +- .../SharePointDsc.SPWebApplication.Tests.ps1 | 135 ++++++- 15 files changed, 706 insertions(+), 241 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9a813d81..cdeb74bc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- SPLogLevel + - Added ReverseDsc export support to this resource +- SPWebApplication + - Added logic to check if specified content database exists in the web + application + - Added possibility to update application pool + +### Fixed + +- ReverseDsc + - Fixed issue where the export would contain duplicate configuration + - Fixed issue where the example export cmdlets was in the incorrect format +- SPDocIcon + - Fixed issue where the resource was using hardcoded SP2016 and later paths + and therefore didn't work in SP2013 +- SPSearchServiceApp + - Fix SQL authentication support with updating DB ownership functions +- SPServiceAppPool + - Fixed issue in Export method where the PsDscRunAsCredential was stored as + a string instead of a PsCredential object +- SPSite + - Fixed issue where the code continues when the creation of the site failed, + throwing even more errors + ## [4.8.0] - 2021-08-31 ### Added diff --git a/SharePointDsc/DSCResources/MSFT_SPDocIcon/MSFT_SPDocIcon.psm1 b/SharePointDsc/DSCResources/MSFT_SPDocIcon/MSFT_SPDocIcon.psm1 index 7599f2b60..8c8e12b82 100644 --- a/SharePointDsc/DSCResources/MSFT_SPDocIcon/MSFT_SPDocIcon.psm1 +++ b/SharePointDsc/DSCResources/MSFT_SPDocIcon/MSFT_SPDocIcon.psm1 @@ -1,8 +1,8 @@ $script:SPDscUtilModulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\Modules\SharePointDsc.Util' Import-Module -Name $script:SPDscUtilModulePath -$dociconPath = Join-Path -Path $env:CommonProgramFiles -ChildPath 'microsoft shared\Web Server Extensions\16\TEMPLATE\XML' -$iconPath = Join-Path -Path $env:CommonProgramFiles -ChildPath 'microsoft shared\Web Server Extensions\16\TEMPLATE\IMAGES' +$dociconPath = Join-Path -Path $env:CommonProgramFiles -ChildPath 'microsoft shared\Web Server Extensions\{0}\TEMPLATE\XML' +$iconPath = Join-Path -Path $env:CommonProgramFiles -ChildPath 'microsoft shared\Web Server Extensions\{0}\TEMPLATE\IMAGES' $dociconFileName = 'DOCICON.XML' $backupFileName = 'DOCICON_Backup_{0}.XML' @@ -55,6 +55,7 @@ function Get-TargetResource return $nullReturn } + $dociconPath = $dociconPath -f (Get-SPDscInstalledProductVersion).FileMajorPart $docIconFilePath = Join-Path -Path $dociconPath -ChildPath $dociconFileName if ((Test-Path -Path $docIconFilePath) -eq $false) @@ -76,6 +77,7 @@ function Get-TargetResource { Write-Verbose -Message "Specifed file type ($FileType) exists in docicon.xml" + $iconPath = $iconPath -f (Get-SPDscInstalledProductVersion).FileMajorPart $iconFilePath = Join-Path -Path $iconPath -ChildPath $xmlNode.Value if (Test-Path -Path $iconFilePath) { @@ -150,6 +152,7 @@ function Set-TargetResource throw $message } + $dociconPath = $dociconPath -f (Get-SPDscInstalledProductVersion).FileMajorPart $docIconFilePath = Join-Path -Path $dociconPath -ChildPath $dociconFileName if ((Test-Path -Path $docIconFilePath) -eq $false) @@ -166,6 +169,8 @@ function Set-TargetResource $xmlDoc.Load($docIconFilePath) $xmlNode = $xmlDoc.SelectSingleNode("//Mapping[@Key='$($FileType.ToLower())']") + $iconPath = $iconPath -f (Get-SPDscInstalledProductVersion).FileMajorPart + $changed = $false if ($Ensure -eq 'Present') { @@ -335,6 +340,7 @@ function Export-TargetResource $Content = '' $params = Get-DSCFakeParameters -ModulePath $module + $dociconPath = $dociconPath -f (Get-SPDscInstalledProductVersion).FileMajorPart $docIconFilePath = Join-Path -Path $dociconPath -ChildPath $dociconFileName if ((Test-Path -Path $docIconFilePath) -eq $false) diff --git a/SharePointDsc/DSCResources/MSFT_SPHealthAnalyzerRuleState/MSFT_SPHealthAnalyzerRuleState.schema.mof b/SharePointDsc/DSCResources/MSFT_SPHealthAnalyzerRuleState/MSFT_SPHealthAnalyzerRuleState.schema.mof index 2785d80de..8f9ab1b75 100644 --- a/SharePointDsc/DSCResources/MSFT_SPHealthAnalyzerRuleState/MSFT_SPHealthAnalyzerRuleState.schema.mof +++ b/SharePointDsc/DSCResources/MSFT_SPHealthAnalyzerRuleState/MSFT_SPHealthAnalyzerRuleState.schema.mof @@ -1,18 +1,3 @@ -/* - -**Example** - - SPHealthAnalyzerRuleState DisableDiskSpaceRule - { - Name = "Drives are at risk of running out of free space." - Enabled = $true - RuleScope = "All Servers" - Schedule = "Daily" - FixAutomatically = $false - InstallAccount = $InstallAccount - } -*/ - [ClassVersion("1.0.0.0"), FriendlyName("SPHealthAnalyzerRuleState")] class MSFT_SPHealthAnalyzerRuleState : OMI_BaseResource { @@ -23,4 +8,3 @@ class MSFT_SPHealthAnalyzerRuleState : OMI_BaseResource [Write, Description("Should the rule fix itself automatically")] Boolean FixAutomatically; [Write, Description("POWERSHELL 4 ONLY: The account to run this resource as, use PsDscRunAsCredential if using PowerShell 5"), EmbeddedInstance("MSFT_Credential")] String InstallAccount; }; - diff --git a/SharePointDsc/DSCResources/MSFT_SPLogLevel/MSFT_SPLogLevel.psm1 b/SharePointDsc/DSCResources/MSFT_SPLogLevel/MSFT_SPLogLevel.psm1 index d5b34d7f5..18a229d82 100644 --- a/SharePointDsc/DSCResources/MSFT_SPLogLevel/MSFT_SPLogLevel.psm1 +++ b/SharePointDsc/DSCResources/MSFT_SPLogLevel/MSFT_SPLogLevel.psm1 @@ -89,69 +89,54 @@ function Get-TargetResource return $null } - #TraceLevels - #if we desire defaults, we will check for default for each item and return as such - if ($DesiredSetting.TraceLevel -eq "Default") + foreach ($currentItem in $CurrentLogItemSettings) { - $SettingAtDefault = $true #assume they are all at default until we find otherwise - foreach ($setting in $CurrentLogItemSettings) #default values can vary for each area/name, need to check each one. + #TraceLevels + #if we desire defaults, we will check for default for each item and return as such + if ($DesiredSetting.TraceLevel -eq "Default") { - if ($setting.TraceSeverity -ne $setting.DefaultTraceSeverity) + if ($currentItem.TraceSeverity -eq $currentItem.DefaultTraceSeverity) { - $SettingAtDefault = $false + $Tracelevel = 'Default' + } + else + { + #return a csv list of current unique trace level settings for the provided Area/Name + $Tracelevel = $currentItem.TraceSeverity } } - - if ($SettingAtDefault) - { - $Tracelevel = 'Default' - } + #default was not specified, so we return the unique current trace severity across all provided settings. else { - #return a csv list of current unique trace level settings for the provided Area/Name - $Tracelevel = [System.String]::Join(",", (($CurrentLogItemSettings.traceseverity) | Select-Object -Unique)) + $Tracelevel = $currentItem.TraceSeverity } - } - #default was not specified, so we return the unique current trace severity across all provided settings. - else - { - $Tracelevel = [System.String]::Join(",", (($CurrentLogItemSettings.traceseverity) | Select-Object -Unique)) - } - #EventLevels - #if we desire defaults, we will check for default and return as such - if ($DesiredSetting.EventLevel -eq "Default") - { - $SettingAtDefault = $true #assume they are all at default until we find otherwise - foreach ($setting in $CurrentLogItemSettings) #default values can vary for each area/name, need to check each one. + #EventLevels + #if we desire defaults, we will check for default and return as such + if ($DesiredSetting.EventLevel -eq "Default") { - if ($setting.EventSeverity -ne $setting.DefaultEventSeverity) + if ($currentItem.EventSeverity -eq $currentItem.DefaultEventSeverity) { - $SettingAtDefault = $false + $Eventlevel = 'Default' + } + else + { + #return a csv list of current unique Event level settings for the provided Area/Name + $Eventlevel = $currentItem.Eventseverity } } - - if ($SettingAtDefault) - { - $Eventlevel = 'Default' - } + #default was not specified, so we return the unique current Event severity across all provided settings. else { - #return a csv list of current unique Event level settings for the provided Area/Name - $Eventlevel = [System.String]::Join(",", (($CurrentLogItemSettings.Eventseverity) | Select-Object -Unique)) + $Eventlevel = $currentItem.Eventseverity } - } - #default was not specified, so we return the unique current Event severity across all provided settings. - else - { - $Eventlevel = [System.String]::Join(",", (($CurrentLogItemSettings.Eventseverity) | Select-Object -Unique)) - } - $CurrentLogLevelSettings += New-Object -TypeName PSObject -Property @{ - Area = $DesiredSetting.Area - Name = $DesiredSetting.Name - TraceLevel = $TraceLevel - EventLevel = $EventLevel + $CurrentLogLevelSettings += New-Object -TypeName PSObject -Property @{ + Area = $currentItem.Area + Name = $currentItem.Name + TraceLevel = $TraceLevel + EventLevel = $EventLevel + } } } @@ -336,17 +321,41 @@ function Test-TargetResource { Write-Verbose -Message "Testing SP Log Level setting for $($DesiredSetting.Area):$($DesiredSetting.Name)" - $CurrentSetting = $CurrentValues.SPLogLevelSetting | Where-Object -FilterScript { $_.Area -eq $DesiredSetting.Area -and $_.Name -eq $DesiredSetting.Name } + if ($DesiredSetting.Area -eq "*") + { + if ($DesiredSetting.Name -eq "*") + { + $CurrentSettings = $CurrentValues.SPLogLevelSetting + } + else + { + $CurrentSettings = $CurrentValues.SPLogLevelSetting | Where-Object -FilterScript { $_.Name -eq $DesiredSetting.Name } + } + } + else + { + if ($DesiredSetting.Name -eq "*") + { + $CurrentSettings = $CurrentValues.SPLogLevelSetting | Where-Object -FilterScript { $_.Area -eq $DesiredSetting.Area } + } + else + { + $CurrentSettings = $CurrentValues.SPLogLevelSetting | Where-Object -FilterScript { $_.Area -eq $DesiredSetting.Area -and $_.Name -eq $DesiredSetting.Name } + } + } - if (($null -ne $DesiredSetting.TraceLevel -and $CurrentSetting.TraceLevel -ne $DesiredSetting.TraceLevel) -or ($null -ne $DesiredSetting.EventLevel -and $CurrentSetting.EventLevel -ne $DesiredSetting.EventLevel)) + foreach ($currentSetting in $CurrentSettings) { - $mismatchedSettings += @{ - Name = $Name - DesiredSetting = $DesiredSetting - $CurrentSetting = $CurrentSetting + if (($null -ne $DesiredSetting.TraceLevel -and $currentSetting.TraceLevel -ne $DesiredSetting.TraceLevel) -or ($null -ne $DesiredSetting.EventLevel -and $currentSetting.EventLevel -ne $DesiredSetting.EventLevel)) + { + $mismatchedSettings += @{ + Name = $Name + DesiredSetting = $DesiredSetting + CurrentSetting = $currentSetting + } + Write-Verbose -Message "SP Log Level setting for $($currentSetting.Area):$($currentSetting.Name) is not in the desired state" + $mismatchedSettingFound = $true } - Write-Verbose -Message "SP Log Level setting for $($DesiredSetting.Area):$($DesiredSetting.Name) is not in the desired state" - $mismatchedSettingFound = $true } } @@ -384,3 +393,48 @@ function Test-TargetResource return $result } + +function Export-TargetResource +{ + $VerbosePreference = "SilentlyContinue" + $ParentModuleBase = Get-Module "SharePointDsc" -ListAvailable | Select-Object -ExpandProperty Modulebase + $module = Join-Path -Path $ParentModuleBase -ChildPath "\DSCResources\MSFT_SPLogLevel\MSFT_SPLogLevel.psm1" -Resolve + + $Content = '' + $params = Get-DSCFakeParameters -ModulePath $module + $PartialContent = " SPLogLevel AllLogLevels`r`n" + $PartialContent += " {`r`n" + + try + { + $params.SPLogLevelSetting = @() + $params.SPLogLevelSetting += New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ + Area = "*" + Name = "*" + TraceLevel = "Default" + EventLevel = "Default" + } -ClientOnly + $results = Get-TargetResource @params + + $results = Repair-Credentials -results $results + + $currentBlock = Get-DSCBlock -Params $results -ModulePath $module + $currentBlock = Convert-DSCStringParamToVariable -DSCBlock $currentBlock -ParameterName "PsDscRunAsCredential" + + # Change hashtable format into CIM Instance format + $currentBlock = $currentBlock -replace "@{", "`r`n MSFT_SPLogLevelItem {" -replace "}", "}," -replace ",\);", "`r`n );" -replace "=", "=`"" -replace "; ", "`"; " -replace "}", "`"}" + + $PartialContent += $currentBlock + $PartialContent += " }`r`n" + $Content += $PartialContent + } + catch + { + $Global:ErrorLog += "[Diagnostic Logging Level]`r`n" + $Global:ErrorLog += "$_`r`n`r`n" + } + + return $Content +} + +Export-ModuleMember -Function *-TargetResource diff --git a/SharePointDsc/DSCResources/MSFT_SPSearchServiceApp/MSFT_SPSearchServiceApp.psm1 b/SharePointDsc/DSCResources/MSFT_SPSearchServiceApp/MSFT_SPSearchServiceApp.psm1 index a9f432630..cb1d901ed 100644 --- a/SharePointDsc/DSCResources/MSFT_SPSearchServiceApp/MSFT_SPSearchServiceApp.psm1 +++ b/SharePointDsc/DSCResources/MSFT_SPSearchServiceApp/MSFT_SPSearchServiceApp.psm1 @@ -160,7 +160,8 @@ function Get-TargetResource Write-Verbose -Message "Checking Admin Database: $adminDB" $farmAccountPermissionsNeedCorrecting = (Confirm-UserIsDBOwner -SQLServer $dbServer ` -Database $adminDB ` - -User $farmAccount) -eq $false + -User $farmAccount ` + -DatabaseCredentials $params.DatabaseCredentials) -eq $false Write-Verbose -Message "Farm Account Permissions Need Correcting: $farmAccountPermissionsNeedCorrecting" Write-Verbose -Message "Checking Analytics reporting Database" @@ -173,7 +174,8 @@ function Get-TargetResource { $farmAccountPermissionsNeedCorrecting = (Confirm-UserIsDBOwner -SQLServer $dbServer ` -Database $analyticsDB ` - -User $farmAccount) -eq $false + -User $farmAccount ` + -DatabaseCredentials $params.DatabaseCredentials) -eq $false } Write-Verbose -Message "Farm Account Permissions Need Correcting: $farmAccountPermissionsNeedCorrecting" } @@ -189,7 +191,8 @@ function Get-TargetResource Write-Verbose -Message "Checking Crawl Database: $crawlDB" $farmAccountPermissionsNeedCorrecting = (Confirm-UserIsDBOwner -SQLServer $dbServer ` -Database $crawlDB ` - -User $farmAccount) -eq $false + -User $farmAccount ` + -DatabaseCredentials $params.DatabaseCredentials) -eq $false Write-Verbose -Message "Farm Account Permissions Need Correcting: $farmAccountPermissionsNeedCorrecting" } } @@ -205,7 +208,8 @@ function Get-TargetResource Write-Verbose -Message "Checking Links Database: $linksDB" $farmAccountPermissionsNeedCorrecting = (Confirm-UserIsDBOwner -SQLServer $dbServer ` -Database $linksDB ` - -User $farmAccount) -eq $false + -User $farmAccount ` + -DatabaseCredentials $params.DatabaseCredentials) -eq $false Write-Verbose -Message "Farm Account Permissions Need Correcting: $farmAccountPermissionsNeedCorrecting" } } @@ -546,11 +550,13 @@ function Set-TargetResource $adminDB = $serviceApp.SearchAdminDatabase.Name if ((Confirm-UserIsDBOwner -SQLServer $dbServer ` -Database $adminDB ` - -User $farmAccount) -eq $false) + -User $farmAccount ` + -DatabaseCredentials $params.DatabaseCredentials) -eq $false) { Set-UserAsDBOwner -SQLServer $dbServer ` -Database $adminDB ` - -User $farmAccount + -User $farmAccount ` + -DatabaseCredentials $params.DatabaseCredentials } Write-Verbose -Message "Checking and correcting Analytics reporting Database" @@ -559,11 +565,13 @@ function Set-TargetResource $analyticsDB = $database.Name if ((Confirm-UserIsDBOwner -SQLServer $dbServer ` -Database $analyticsDB ` - -User $farmAccount) -eq $false) + -User $farmAccount ` + -DatabaseCredentials $params.DatabaseCredentials) -eq $false) { Set-UserAsDBOwner -SQLServer $dbServer ` -Database $analyticsDB ` - -User $farmAccount + -User $farmAccount ` + -DatabaseCredentials $params.DatabaseCredentials } } @@ -576,11 +584,13 @@ function Set-TargetResource $dbServer = $database.Database.NormalizedDataSource if ((Confirm-UserIsDBOwner -SQLServer $dbServer ` -Database $crawlDB ` - -User $farmAccount) -eq $false) + -User $farmAccount ` + -DatabaseCredentials $params.DatabaseCredentials) -eq $false) { Set-UserAsDBOwner -SQLServer $dbServer ` -Database $crawlDB ` - -User $farmAccount + -User $farmAccount ` + -DatabaseCredentials $params.DatabaseCredentials } } @@ -593,11 +603,13 @@ function Set-TargetResource $dbServer = $database.Database.NormalizedDataSource if ((Confirm-UserIsDBOwner -SQLServer $dbServer ` -Database $linksDB ` - -User $farmAccount) -eq $false) + -User $farmAccount ` + -DatabaseCredentials $params.DatabaseCredentials) -eq $false) { Set-UserAsDBOwner -SQLServer $dbServer ` -Database $linksDB ` - -User $farmAccount + -User $farmAccount ` + -DatabaseCredentials $params.DatabaseCredentials } } } diff --git a/SharePointDsc/DSCResources/MSFT_SPServiceAppPool/MSFT_SPServiceAppPool.psm1 b/SharePointDsc/DSCResources/MSFT_SPServiceAppPool/MSFT_SPServiceAppPool.psm1 index 283a3dfed..f4a52d715 100644 --- a/SharePointDsc/DSCResources/MSFT_SPServiceAppPool/MSFT_SPServiceAppPool.psm1 +++ b/SharePointDsc/DSCResources/MSFT_SPServiceAppPool/MSFT_SPServiceAppPool.psm1 @@ -222,8 +222,8 @@ function Export-TargetResource if ($convertToVariable) { $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "ServiceAccount" - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "PsDscRunAsCredential" } + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "PsDscRunAsCredential" $PartialContent += $currentDSCBlock $PartialContent += " }`r`n" diff --git a/SharePointDsc/DSCResources/MSFT_SPSite/MSFT_SPSite.psm1 b/SharePointDsc/DSCResources/MSFT_SPSite/MSFT_SPSite.psm1 index dc7bf6bfa..342b2e70a 100644 --- a/SharePointDsc/DSCResources/MSFT_SPSite/MSFT_SPSite.psm1 +++ b/SharePointDsc/DSCResources/MSFT_SPSite/MSFT_SPSite.psm1 @@ -299,8 +299,9 @@ function Set-TargetResource { Write-Verbose -Message ("Starting New-SPSite with the following parameters: " + ` "$(Convert-SPDscHashtableToString $params)") - #$site = New-SPSite @params + # Implemented alternative solution (not using New-SPSite) to mitigate a timing + # issue which exists shortly after creating a new farm. $paramsList = $params.GetEnumerator() | Where-Object { $_.Key -ne "Verbose" } | ForEach-Object { @@ -334,10 +335,25 @@ function Set-TargetResource -PassThru if ($result.ExitCode -ne 0) { - throw ("[ERROR] An error during site creation. Exit code '$($result.ExitCode)' " + ` + $message = ("[ERROR] An error during site creation. Exit code '$($result.ExitCode)' " + ` "was returned. Please check ULS log for more info") + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $eventSource + throw $message } + $site = Get-SPSite -Identity $params.Url -ErrorAction SilentlyContinue + if ($null -eq $site) + { + $message = "Cannot find created site collection, please check ULS log for any error messages!" + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $eventSource + throw $message + } if ($CreateDefaultGroups -eq $true) { diff --git a/SharePointDsc/DSCResources/MSFT_SPWebApplication/MSFT_SPWebApplication.psm1 b/SharePointDsc/DSCResources/MSFT_SPWebApplication/MSFT_SPWebApplication.psm1 index 1934b4527..afe11c85e 100644 --- a/SharePointDsc/DSCResources/MSFT_SPWebApplication/MSFT_SPWebApplication.psm1 +++ b/SharePointDsc/DSCResources/MSFT_SPWebApplication/MSFT_SPWebApplication.psm1 @@ -101,14 +101,24 @@ function Get-TargetResource { $IISPath = $IISPath.ToString() } + + $contentDb = $wa.ContentDatabases | Where-Object -FilterScript { + $_.Name -eq $params.DatabaseName + } + + if ($null -eq $contentDb) + { + $contentDb = $wa.ContentDatabases[0] + } + return @{ Name = $wa.DisplayName ApplicationPool = $wa.ApplicationPool.Name ApplicationPoolAccount = $wa.ApplicationPool.Username WebAppUrl = $wa.Url AllowAnonymous = $authProvider.AllowAnonymous - DatabaseName = $wa.ContentDatabases[0].Name - DatabaseServer = $wa.ContentDatabases[0].Server + DatabaseName = $contentDb.Name + DatabaseServer = $contentDb.Server HostHeader = (New-Object -TypeName System.Uri $wa.Url).Host Path = $IISPath Port = (New-Object -TypeName System.Uri $wa.Url).Port @@ -202,6 +212,8 @@ function Set-TargetResource $wa = Get-SPWebApplication -Identity $params.Name -ErrorAction SilentlyContinue if ($null -eq $wa) { + Write-Verbose -Message "Creating new web application" + $newWebAppParams = @{ Name = $params.Name ApplicationPool = $params.ApplicationPool @@ -292,8 +304,102 @@ function Set-TargetResource Write-Verbose -Message "`$useSQLAuthentication is false or not specified; using default Windows authentication." } + Write-Verbose -Message "Creating web application with these parameters: $(Convert-SPDscHashtableToString -Hashtable $newWebAppParams)" New-SPWebApplication @newWebAppParams | Out-Null } + else + { + Write-Verbose -Message "Update existing web application" + if ($params.ContainsKey("DatabaseName") -eq $true) + { + Write-Verbose -Message "Checking content database '$($params.DatabaseName)'" + $contentDb = $wa.ContentDatabases | Where-Object -FilterScript { + $_.Name -eq $params.DatabaseName + } + + if ($null -eq $contentDb) + { + Write-Verbose -Message "Specified content database does not exist, creating database" + $dbParams = @{ + WebApplication = $params.WebAppUrl + Name = $params.DatabaseName + } + if ($params.ContainsKey("DatabaseServer") -eq $true) + { + $dbParams.Add("DatabaseServer", $params.DatabaseServer) + } + + try + { + $null = Mount-SPContentDatabase @dbParams -ErrorAction Stop + } + catch + { + $message = ("Error occurred while mounting content database. " + ` + "Content database is not mounted. " + ` + "Error details: $($_.Exception.Message)") + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $eventSource + throw $message + } + } + } + + # Application Pool + if ($wa.ApplicationPool.Name -ne $params.ApplicationPool) + { + Write-Verbose -Message "Updating application pool for web application" + + $admService = Get-SPDscContentService + $newAppPool = $admService.ApplicationPools | Where-Object -FilterScript { + $_.Name -eq $params.ApplicationPool + } + if ($null -eq $newAppPool) + { + Write-Verbose -Message "Checking Managed Account for specified Application Pool account" + $managedAccount = Get-SPManagedAccount -Identity $params.ApplicationPoolAccount ` + -ErrorAction SilentlyContinue + + if ($null -eq $managedAccount) + { + $message = ("Specified ApplicationPoolAccount '$($params.ApplicationPoolAccount)' " + ` + "is not a managed account") + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $eventSource + throw $message + } + + try + { + Write-Verbose -Message "Specified application pool doesn't exist. Creating new application pool." + $newAppPool = New-Object Microsoft.SharePoint.Administration.SPApplicationPool($params.ApplicationPool, $admService) + $newAppPool.CurrentIdentityType = "SpecificUser" + $newAppPool.Username = $params.ApplicationPoolAccount + $newAppPool.Update($true) + $newAppPool.Provision() + } + catch + { + $message = ("Error while creating new application pool. " + + "Error details: $($_.Exception.Message)") + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $eventSource + throw $message + } + } + + Write-Verbose -Message "Applying new application pool" + $wa.ApplicationPool = $newAppPool + $wa.Update() + $wa.ProvisionGlobally() + } + } } } @@ -307,6 +413,7 @@ function Set-TargetResource $wa = Get-SPWebApplication -Identity $params.Name -ErrorAction SilentlyContinue if ($null -ne $wa) { + Write-Verbose -Message "Deleting web application $($params.Name)" $wa | Remove-SPWebApplication -Confirm:$false -DeleteIISSite } } @@ -393,7 +500,7 @@ function Test-TargetResource $result = Test-SPDscParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` -DesiredValues $PSBoundParameters ` - -ValuesToCheck @("Ensure") + -ValuesToCheck @("ApplicationPool", "DatabaseName", "Ensure") Write-Verbose -Message "Test-TargetResource returned $result" diff --git a/SharePointDsc/Modules/SharePointDsc.Reverse/SharePointDsc.Reverse.psm1 b/SharePointDsc/Modules/SharePointDsc.Reverse/SharePointDsc.Reverse.psm1 index b1cddaa1b..c303e91c6 100644 --- a/SharePointDsc/Modules/SharePointDsc.Reverse/SharePointDsc.Reverse.psm1 +++ b/SharePointDsc/Modules/SharePointDsc.Reverse/SharePointDsc.Reverse.psm1 @@ -304,7 +304,7 @@ function Orchestrator $i++ } } - $Script:dscConfigContent += "<# Generated with SharePointDSC " + $script:version + " #>`r`n" + $Script:dscConfigContent = "<# Generated with SharePointDSC " + $script:version + " #>`r`n" Write-Host -Object "Scanning Operating System Version..." -BackgroundColor DarkGreen -ForegroundColor White $Script:dscConfigContent += Read-OperatingSystemVersion @@ -382,6 +382,9 @@ function Orchestrator Write-Host -Object "[$($spServer.Name)] Scanning Diagnostic Logging Settings..." -BackgroundColor DarkGreen -ForegroundColor White $Script:dscConfigContent += Read-TargetResource -ResourceName 'SPDiagnosticLoggingSettings' + Write-Host -Object "[$($spServer.Name)] Scanning Diagnostic Logging Levels..." -BackgroundColor DarkGreen -ForegroundColor White + $Script:dscConfigContent += Read-TargetResource -ResourceName 'SPLogLevel' + Write-Host -Object "[$($spServer.Name)] Scanning Usage Service Application..." -BackgroundColor DarkGreen -ForegroundColor White $Script:dscConfigContent += Read-TargetResource -ResourceName 'SPUsageApplication' @@ -1149,27 +1152,27 @@ function DisplayGUI() @{ Name = "SPManagedAccount" Text = "Managed Accounts" - ExtractionMode = 1 + ExtractionMode = 1 }, @{ Name = "SPPasswordChangeSettings" Text = "Password Change Settings" - ExtractionMode = 2 + ExtractionMode = 2 }, @{ Name = "SPRemoteFarmTrust" Text = "Remote Farm Trusts" - ExtractionMode = 2 + ExtractionMode = 2 }, @{ Name = "SPServiceAppSecurity" Text = "Service App Security" - ExtractionMode = 2 + ExtractionMode = 2 }, @{ Name = "SPTrustedIdentityTokenIssuer" Text = "Trusted Identity Token Issuers" - ExtractionMode = 2 + ExtractionMode = 2 } ) ServiceApplications = @( @@ -1401,6 +1404,11 @@ function DisplayGUI() Text = "Cache Accounts" ExtractionMode = 1 }, + @{ + Name = "SPLogLevel" + Text = "Diagnostic Logging Levels" + ExtractionMode = 1 + }, @{ Name = "SPDiagnosticLoggingSettings"; Text = "Diagnostic Logging Settings" @@ -2031,7 +2039,7 @@ function DisplayGUI() } } $form.Hide() - $componentsToString = "@(`"$($SelectedComponents -join "`",`"")`")" + $componentsToString = "@(`"" + ($SelectedComponents -join "`",`"") + "`")" Write-Host -Object "To execute the same extraction process unattended, run the following command:" -BackgroundColor DarkGreen -ForegroundColor White Write-Host -Object "Export-SPConfiguration -ComponentsToExtract $componentsToString -Credentials (Get-Credential)" diff --git a/SharePointDsc/Modules/SharePointDsc.Search/SPSearchServiceApp.psm1 b/SharePointDsc/Modules/SharePointDsc.Search/SPSearchServiceApp.psm1 index c87363aba..2455a0c68 100644 --- a/SharePointDsc/Modules/SharePointDsc.Search/SPSearchServiceApp.psm1 +++ b/SharePointDsc/Modules/SharePointDsc.Search/SPSearchServiceApp.psm1 @@ -26,7 +26,8 @@ function Confirm-UserIsDBOwner $command = New-Object -TypeName "System.Data.SqlClient.SqlCommand" # If we specified SQL credentials then try to use them - if ($PSBoundParameters.ContainsKey("DatabaseCredentials")) + if ($PSBoundParameters.ContainsKey("DatabaseCredentials") -and ` + [System.String]::IsNullOrEmpty($DatabaseCredentials) -eq $false) { $marshal = [Runtime.InteropServices.Marshal] $dbCredentialsPlainPassword = $marshal::PtrToStringAuto($marshal::SecureStringToBSTR($DatabaseCredentials.Password)) @@ -99,7 +100,8 @@ function Set-UserAsDBOwner $command = New-Object -TypeName "System.Data.SqlClient.SqlCommand" # If we specified SQL credentials then try to use them - if ($PSBoundParameters.ContainsKey("DatabaseCredentials")) + if ($PSBoundParameters.ContainsKey("DatabaseCredentials") -and ` + [System.String]::IsNullOrEmpty($DatabaseCredentials) -eq $false) { $marshal = [Runtime.InteropServices.Marshal] $dbCredentialsPlainPassword = $marshal::PtrToStringAuto($marshal::SecureStringToBSTR($DatabaseCredentials.Password)) diff --git a/SharePointDsc/Modules/SharePointDsc.Util/SharePointDsc.Util.psm1 b/SharePointDsc/Modules/SharePointDsc.Util/SharePointDsc.Util.psm1 index 75b038376..952520de5 100644 --- a/SharePointDsc/Modules/SharePointDsc.Util/SharePointDsc.Util.psm1 +++ b/SharePointDsc/Modules/SharePointDsc.Util/SharePointDsc.Util.psm1 @@ -436,7 +436,7 @@ function Get-SPDscFarmVersionInfo ($patchableUnit -notmatch "XMUI") -and ($patchableUnit -notmatch "Project Server") -and (($patchableUnit -notmatch "Microsoft SharePoint Server (2013|2016|2019)" -or ` - $patchableUnit -match "Core"))) + $patchableUnit -match "Core"))) { $patchableUnitsInfo = $singleProductInfo.GetPatchableUnitInfoByDisplayName($patchableUnit) $currentVersion = "" @@ -1620,6 +1620,7 @@ function Export-SPConfiguration <## Scripts Variables #> $Script:DH_SPQUOTATEMPLATE = @{} $Script:dscConfigContent = "" + $Global:CredsRepo = @() $Global:AllUsers = @() $Script:ErrorLog = "" $Script:configName = "" diff --git a/tests/Unit/SharePointDsc/SharePointDsc.SPDocIcon.Tests.ps1 b/tests/Unit/SharePointDsc/SharePointDsc.SPDocIcon.Tests.ps1 index 4304a90e0..fc76a3654 100644 --- a/tests/Unit/SharePointDsc/SharePointDsc.SPDocIcon.Tests.ps1 +++ b/tests/Unit/SharePointDsc/SharePointDsc.SPDocIcon.Tests.ps1 @@ -50,7 +50,7 @@ try InModuleScope -ModuleName $script:DSCResourceFullName -ScriptBlock { Describe -Name $Global:SPDscHelper.DescribeHeader -Fixture { BeforeAll { - Invoke-Command -Scriptblock $Global:SPDscHelper.InitializeScript -NoNewScope + Invoke-Command -ScriptBlock $Global:SPDscHelper.InitializeScript -NoNewScope # Initialize tests $mockPassword = ConvertTo-SecureString -String 'password' -AsPlainText -Force @@ -165,7 +165,7 @@ try Mock -CommandName Test-Path -MockWith { return $false - } -ParameterFilter { $Path -eq 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\TEMPLATE\XML\docicon.xml' } + } -ParameterFilter { $Path -eq "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\$($Global:SPDscHelper.CurrentStubBuildNumber.Major)\TEMPLATE\XML\docicon.xml" } } It 'Should return Ensure=Absent from the Get method' { @@ -173,7 +173,7 @@ try } It 'Should throw parameter validation exception in the Set method' { - { Set-TargetResource @testParams } | Should -Throw "Docicon.xml file is not found: C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\TEMPLATE\XML\docicon.xml" + { Set-TargetResource @testParams } | Should -Throw "Docicon.xml file is not found: C:\Program Files\Common Files\microsoft shared\Web Server Extensions\$($Global:SPDscHelper.CurrentStubBuildNumber.Major)\TEMPLATE\XML\docicon.xml" } It 'Should return false from the Test method' { @@ -197,7 +197,7 @@ try Mock -CommandName Test-Path -MockWith { return $false - } -ParameterFilter { $Path -eq 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\TEMPLATE\IMAGES\icpdf.png' } + } -ParameterFilter { $Path -eq "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\$($Global:SPDscHelper.CurrentStubBuildNumber.Major)\TEMPLATE\IMAGES\icpdf.png" } Mock -CommandName Copy-Item -MockWith {} @@ -215,7 +215,7 @@ try '@ Mock -CommandName Join-Path -MockWith { return $dociconFile - } -ParameterFilter { $Path -eq 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\TEMPLATE\XML' } + } -ParameterFilter { $Path -eq "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\$($Global:SPDscHelper.CurrentStubBuildNumber.Major)\TEMPLATE\XML" } } It 'Should return Ensure=Absent from the Get method' { @@ -260,7 +260,7 @@ try return @{ Hash = "gfedcba" } - } -ParameterFilter { $Path -eq 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\TEMPLATE\IMAGES\icpdf.png' } + } -ParameterFilter { $Path -eq "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\$($Global:SPDscHelper.CurrentStubBuildNumber.Major)\TEMPLATE\IMAGES\icpdf.png" } Mock -CommandName Copy-Item -MockWith {} @@ -278,7 +278,7 @@ try '@ Mock -CommandName Join-Path -MockWith { return $dociconFile - } -ParameterFilter { $Path -eq 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\TEMPLATE\XML' } + } -ParameterFilter { $Path -eq "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\$($Global:SPDscHelper.CurrentStubBuildNumber.Major)\TEMPLATE\XML" } } It 'Should return Ensure=Absent from the Get method' { @@ -334,7 +334,7 @@ try '@ Mock -CommandName Join-Path -MockWith { return $dociconFile - } -ParameterFilter { $Path -eq 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\TEMPLATE\XML' } + } -ParameterFilter { $Path -eq "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\$($Global:SPDscHelper.CurrentStubBuildNumber.Major)\TEMPLATE\XML" } } It 'Should return Ensure=Absent from the Get method' { @@ -390,7 +390,7 @@ try '@ Mock -CommandName Join-Path -MockWith { return $dociconFile - } -ParameterFilter { $Path -eq 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\TEMPLATE\XML' } + } -ParameterFilter { $Path -eq "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\$($Global:SPDscHelper.CurrentStubBuildNumber.Major)\TEMPLATE\XML" } } It 'Should return Ensure=Present from the Get method' { @@ -460,7 +460,7 @@ try '@ Mock -CommandName Join-Path -MockWith { return $dociconFile - } -ParameterFilter { $Path -eq 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\TEMPLATE\XML' } + } -ParameterFilter { $Path -eq "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\$($Global:SPDscHelper.CurrentStubBuildNumber.Major)\TEMPLATE\XML" } } It 'Should return Ensure=Present from the Get method' { @@ -504,7 +504,7 @@ try '@ Mock -CommandName Join-Path -MockWith { return $dociconFile - } -ParameterFilter { $Path -eq 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\TEMPLATE\XML' } + } -ParameterFilter { $Path -eq "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\$($Global:SPDscHelper.CurrentStubBuildNumber.Major)\TEMPLATE\XML" } } It 'Should return Ensure=Present from the Get method' { @@ -551,7 +551,7 @@ try Mock -CommandName Join-Path -MockWith { return $dociconFile - } -ParameterFilter { $Path -eq 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\TEMPLATE\XML' } + } -ParameterFilter { $Path -eq "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\$($Global:SPDscHelper.CurrentStubBuildNumber.Major)\TEMPLATE\XML" } } It 'Should return Ensure=Absent from the Get method' { @@ -598,7 +598,7 @@ try Mock -CommandName Join-Path -MockWith { return $dociconFile - } -ParameterFilter { $Path -eq 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\TEMPLATE\XML' } + } -ParameterFilter { $Path -eq "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\$($Global:SPDscHelper.CurrentStubBuildNumber.Major)\TEMPLATE\XML" } if ($null -eq (Get-Variable -Name 'spFarmAccount' -ErrorAction SilentlyContinue)) { diff --git a/tests/Unit/SharePointDsc/SharePointDsc.SPLogLevel.Tests.ps1 b/tests/Unit/SharePointDsc/SharePointDsc.SPLogLevel.Tests.ps1 index 6565057dc..4adeb0719 100644 --- a/tests/Unit/SharePointDsc/SharePointDsc.SPLogLevel.Tests.ps1 +++ b/tests/Unit/SharePointDsc/SharePointDsc.SPLogLevel.Tests.ps1 @@ -84,11 +84,11 @@ try Name = "My LogLevel Settings" SPLogLevelSetting = @( (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePoint Server", "Excel Services Application" - Name = "*" - TraceLevel = "Medium" - EventLevel = "Information" - } -ClientOnly) + Area = "SharePoint Server", "Excel Services Application" + Name = "*" + TraceLevel = "Medium" + EventLevel = "Information" + } -ClientOnly) ) } } @@ -112,11 +112,11 @@ try Name = "My LogLevel Settings" SPLogLevelSetting = @( (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePointServer" - Name = "Database", "UserProfile" - TraceLevel = "Medium" - EventLevel = "Information" - } -ClientOnly) + Area = "SharePointServer" + Name = "Database", "UserProfile" + TraceLevel = "Medium" + EventLevel = "Information" + } -ClientOnly) ) } } @@ -140,9 +140,9 @@ try Name = "My LogLevel Settings" SPLogLevelSetting = @( (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePointServer" - Name = "Database" - } -ClientOnly) + Area = "SharePointServer" + Name = "Database" + } -ClientOnly) ) } } @@ -166,11 +166,11 @@ try Name = "My LogLevel Settings" SPLogLevelSetting = @( (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePointServer" - Name = "Database" - TraceLevel = "detailed" - EventLevel = "Information" - } -ClientOnly) + Area = "SharePointServer" + Name = "Database" + TraceLevel = "detailed" + EventLevel = "Information" + } -ClientOnly) ) } } @@ -194,11 +194,11 @@ try Name = "My LogLevel Settings" SPLogLevelSetting = @( (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePoint Server" - Name = "Database" - TraceLevel = "Medium" - EventLevel = "detailed" - } -ClientOnly) + Area = "SharePoint Server" + Name = "Database" + TraceLevel = "Medium" + EventLevel = "detailed" + } -ClientOnly) ) } } @@ -222,11 +222,11 @@ try Name = "My LogLevel Settings" SPLogLevelSetting = @( (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePoint Server" - Name = "Database" - TraceLevel = "Default" - EventLevel = "Default" - } -ClientOnly) + Area = "SharePoint Server" + Name = "Database" + TraceLevel = "Default" + EventLevel = "Default" + } -ClientOnly) ) } @@ -262,11 +262,11 @@ try Name = "My LogLevel Settings" SPLogLevelSetting = @( (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePoint Server" - Name = "Database" - TraceLevel = "Default" - EventLevel = "Default" - } -ClientOnly) + Area = "SharePoint Server" + Name = "Database" + TraceLevel = "Default" + EventLevel = "Default" + } -ClientOnly) ) } @@ -304,11 +304,11 @@ try Name = "My LogLevel Settings" SPLogLevelSetting = @( (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePoint Server" - Name = "Database" - TraceLevel = "Unexpected" - EventLevel = "Error" - } -ClientOnly) + Area = "SharePoint Server" + Name = "Database" + TraceLevel = "Unexpected" + EventLevel = "Error" + } -ClientOnly) ) } @@ -342,11 +342,11 @@ try Name = "My LogLevel Settings" SPLogLevelSetting = @( (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePoint Server" - Name = "Database" - TraceLevel = "Unexpected" - EventLevel = "Error" - } -ClientOnly) + Area = "SharePoint Server" + Name = "Database" + TraceLevel = "Unexpected" + EventLevel = "Error" + } -ClientOnly) ) } @@ -384,11 +384,11 @@ try Name = "My LogLevel Settings" SPLogLevelSetting = @( (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePoint Server" - Name = "*" - TraceLevel = "Medium" - EventLevel = "Information" - } -ClientOnly) + Area = "SharePoint Server" + Name = "*" + TraceLevel = "Medium" + EventLevel = "Information" + } -ClientOnly) ) } @@ -424,8 +424,8 @@ try It "Should return values from the get method [TraceLevel] and [EventLevel]" { $result = Get-TargetResource @testParams - $result.SPLogLevelSetting.TraceLevel | Should -Be "Medium" - $result.SPLogLevelSetting.EventLevel | Should -Be "Information" + $result.SPLogLevelSetting.TraceLevel | Should -Be @("Medium", "Medium", "Medium") + $result.SPLogLevelSetting.EventLevel | Should -Be @("Information", "Information", "Information") } It "Should return true from the test method" { @@ -439,11 +439,11 @@ try Name = "My LogLevel Settings" SPLogLevelSetting = @( (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePoint Server" - Name = "*" - TraceLevel = "Medium" - EventLevel = "Information" - } -ClientOnly) + Area = "SharePoint Server" + Name = "*" + TraceLevel = "Medium" + EventLevel = "Information" + } -ClientOnly) ) } @@ -479,8 +479,8 @@ try It "Should return values from the get method [TraceLevel] and [EventLevel]" { $result = Get-TargetResource @testParams - $result.SPLogLevelSetting.TraceLevel | Should -Be "Medium,Verbose" - $result.SPLogLevelSetting.EventLevel | Should -Be "Information" + $result.SPLogLevelSetting.TraceLevel | Should -Be @("Medium", "Medium", "Verbose") + $result.SPLogLevelSetting.EventLevel | Should -Be @("Information", "Information", "Information") } It "Should return false from the test method" { @@ -500,11 +500,11 @@ try Name = "My LogLevel Settings" SPLogLevelSetting = @( (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "*" - Name = "*" - TraceLevel = "Default" - EventLevel = "Default" - } -ClientOnly) + Area = "*" + Name = "*" + TraceLevel = "Default" + EventLevel = "Default" + } -ClientOnly) ) } @@ -564,8 +564,8 @@ try It "Should return values from the get method [TraceLevel] and [EventLevel]" { $result = Get-TargetResource @testParams - $result.SPLogLevelSetting.TraceLevel | Should -Be "Default" - $result.SPLogLevelSetting.EventLevel | Should -Be "Default" + $result.SPLogLevelSetting.TraceLevel | Should -Be @("Default", "Default", "Default", "Default", "Default", "Default") + $result.SPLogLevelSetting.EventLevel | Should -Be @("Default", "Default", "Default", "Default", "Default", "Default") } It "Should return true from the test method" { @@ -579,11 +579,11 @@ try Name = "My LogLevel Settings" SPLogLevelSetting = @( (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "*" - Name = "*" - TraceLevel = "Medium" - EventLevel = "Verbose" - } -ClientOnly) + Area = "*" + Name = "*" + TraceLevel = "Medium" + EventLevel = "Verbose" + } -ClientOnly) ) } @@ -643,8 +643,8 @@ try It "Should return values from the get method [TraceLevel] and [EventLevel]" { $result = Get-TargetResource @testParams - $result.SPLogLevelSetting.TraceLevel | Should -Be "Medium" - $result.SPLogLevelSetting.EventLevel | Should -Be "Information" + $result.SPLogLevelSetting.TraceLevel | Should -Be @("Medium", "Medium", "Medium", "Medium", "Medium", "Medium") + $result.SPLogLevelSetting.EventLevel | Should -Be @("Information", "Information", "Information", "Information", "Information", "Information") } It "Should return false from the test method" { @@ -663,17 +663,17 @@ try Name = "My LogLevel Settings" SPLogLevelSetting = @( (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePoint Server" - Name = "Database" - TraceLevel = "Unexpected" - EventLevel = "Error" - } -ClientOnly) + Area = "SharePoint Server" + Name = "Database" + TraceLevel = "Unexpected" + EventLevel = "Error" + } -ClientOnly) (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePoint Server" - Name = "User Profile" - TraceLevel = "None" - EventLevel = "Warning" - } -ClientOnly) + Area = "SharePoint Server" + Name = "User Profile" + TraceLevel = "None" + EventLevel = "Warning" + } -ClientOnly) ) } @@ -681,15 +681,28 @@ try Mock -CommandName Get-SPLogLevel -MockWith { return @( @{ - Area = "placeholder" - Name = "placeholder" + Area = "SharePoint Server" + Name = "Database" TraceSeverity = "Medium" EventSeverity = "Information" DefaultTraceSeverity = "Medium" DefaultEventSeverity = "Information" } ) - } + } -ParameterFilter { $Identity -eq "SharePoint Server:Database" } + + Mock -CommandName Get-SPLogLevel -MockWith { + return @( + @{ + Area = "SharePoint Server" + Name = "User Profile" + TraceSeverity = "Medium" + EventSeverity = "Information" + DefaultTraceSeverity = "Medium" + DefaultEventSeverity = "Information" + } + ) + } -ParameterFilter { $Identity -eq "SharePoint Server:User Profile" } } It "Should return values from the get method [TraceLevel and EventLevel, first and second item]" { @@ -716,17 +729,17 @@ try Name = "My LogLevel Settings" SPLogLevelSetting = @( (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePoint Server" - Name = "Database" - TraceLevel = "Medium" - EventLevel = "Information" - } -ClientOnly) + Area = "SharePoint Server" + Name = "Database" + TraceLevel = "Medium" + EventLevel = "Information" + } -ClientOnly) (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePoint Server" - Name = "User Profile" - TraceLevel = "Medium" - EventLevel = "Information" - } -ClientOnly) + Area = "SharePoint Server" + Name = "User Profile" + TraceLevel = "Medium" + EventLevel = "Information" + } -ClientOnly) ) } @@ -734,15 +747,28 @@ try Mock -CommandName Get-SPLogLevel -MockWith { return @( @{ - Area = "placeholder" - Name = "placeholder" + Area = "SharePoint Server" + Name = "Database" TraceSeverity = "Medium" EventSeverity = "Information" DefaultTraceSeverity = "Medium" DefaultEventSeverity = "Information" } ) - } + } -ParameterFilter { $Identity -eq "SharePoint Server:Database" } + + Mock -CommandName Get-SPLogLevel -MockWith { + return @( + @{ + Area = "SharePoint Server" + Name = "User Profile" + TraceSeverity = "Medium" + EventSeverity = "Information" + DefaultTraceSeverity = "Medium" + DefaultEventSeverity = "Information" + } + ) + } -ParameterFilter { $Identity -eq "SharePoint Server:User Profile" } } It "Should return values from the get method [TraceLevel and EventLevel, first and second item]" { @@ -764,17 +790,17 @@ try Name = "My LogLevel Settings" SPLogLevelSetting = @( (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePoint Server" - Name = "Database" - TraceLevel = "Default" - EventLevel = "Default" - } -ClientOnly) + Area = "SharePoint Server" + Name = "Database" + TraceLevel = "Default" + EventLevel = "Default" + } -ClientOnly) (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePoint Server" - Name = "User Profile" - TraceLevel = "Default" - EventLevel = "Default" - } -ClientOnly) + Area = "SharePoint Server" + Name = "User Profile" + TraceLevel = "Default" + EventLevel = "Default" + } -ClientOnly) ) } @@ -782,15 +808,28 @@ try Mock -CommandName Get-SPLogLevel -MockWith { return @( @{ - Area = "placeholder" - Name = "placeholder" + Area = "SharePoint Server" + Name = "Database" TraceSeverity = "Medium" EventSeverity = "Information" DefaultTraceSeverity = "Medium" DefaultEventSeverity = "Information" } ) - } + } -ParameterFilter { $Identity -eq "SharePoint Server:Database" } + + Mock -CommandName Get-SPLogLevel -MockWith { + return @( + @{ + Area = "SharePoint Server" + Name = "User Profile" + TraceSeverity = "Medium" + EventSeverity = "Information" + DefaultTraceSeverity = "Medium" + DefaultEventSeverity = "Information" + } + ) + } -ParameterFilter { $Identity -eq "SharePoint Server:User Profile" } } It "Should return Default from the get method [TraceLevel and EventLevel, first and second item]" { @@ -812,17 +851,17 @@ try Name = "My LogLevel Settings" SPLogLevelSetting = @( (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePoint Server" - Name = "Database" - TraceLevel = "Default" - EventLevel = "Default" - } -ClientOnly) + Area = "SharePoint Server" + Name = "Database" + TraceLevel = "Default" + EventLevel = "Default" + } -ClientOnly) (New-CimInstance -ClassName MSFT_SPLogLevelItem -Property @{ - Area = "SharePoint Server" - Name = "User Profile" - TraceLevel = "Default" - EventLevel = "Default" - } -ClientOnly) + Area = "SharePoint Server" + Name = "User Profile" + TraceLevel = "Default" + EventLevel = "Default" + } -ClientOnly) ) } @@ -830,15 +869,28 @@ try Mock -CommandName Get-SPLogLevel -MockWith { return @( @{ - Area = "placeholder" - Name = "placeholder" + Area = "SharePoint Server" + Name = "Database" TraceSeverity = "Verbose" EventSeverity = "Warning" DefaultTraceSeverity = "Medium" DefaultEventSeverity = "Information" } ) - } + } -ParameterFilter { $Identity -eq "SharePoint Server:Database" } + + Mock -CommandName Get-SPLogLevel -MockWith { + return @( + @{ + Area = "SharePoint Server" + Name = "User Profile" + TraceSeverity = "Verbose" + EventSeverity = "Warning" + DefaultTraceSeverity = "Medium" + DefaultEventSeverity = "Information" + } + ) + } -ParameterFilter { $Identity -eq "SharePoint Server:User Profile" } } It "Should return Default from the get method [TraceLevel and EventLevel, first and second item]" { @@ -858,6 +910,74 @@ try Assert-MockCalled Set-SPLogLevel } } + + Context -Name "Running ReverseDsc Export" -Fixture { + BeforeAll { + Import-Module (Join-Path -Path (Split-Path -Path (Get-Module SharePointDsc -ListAvailable).Path -Parent) -ChildPath "Modules\SharePointDSC.Reverse\SharePointDSC.Reverse.psm1") + + Mock -CommandName Write-Host -MockWith { } + + Mock -CommandName Get-TargetResource -MockWith { + $CurrentLogLevelSettings = @() + $CurrentLogLevelSettings += New-Object -TypeName PSObject -Property @{ + Area = "Access Services" + Name = "Administration" + TraceLevel = "Default" + EventLevel = "Default" + } + $CurrentLogLevelSettings += New-Object -TypeName PSObject -Property @{ + Area = "SharePoint Server" + Name = "General" + TraceLevel = "Default" + EventLevel = "Default" + } + + return @{ + Name = "Export" + SPLogLevelSetting = $CurrentLogLevelSettings + } + } + + if ($null -eq (Get-Variable -Name 'spFarmAccount' -ErrorAction SilentlyContinue)) + { + $mockPassword = ConvertTo-SecureString -String "password" -AsPlainText -Force + $Global:spFarmAccount = New-Object -TypeName System.Management.Automation.PSCredential ("contoso\spfarm", $mockPassword) + } + + if ($null -eq (Get-Variable -Name 'DynamicCompilation' -ErrorAction SilentlyContinue)) + { + $DynamicCompilation = $false + } + + if ($null -eq (Get-Variable -Name 'StandAlone' -ErrorAction SilentlyContinue)) + { + $StandAlone = $true + } + + if ($null -eq (Get-Variable -Name 'ExtractionModeValue' -ErrorAction SilentlyContinue)) + { + $Global:ExtractionModeValue = 2 + $Global:ComponentsToExtract = @('SPFarm') + } + + $result = @' + SPLogLevel AllLogLevels + { + Name =" "Export"; + PsDscRunAsCredential =" $Credsspfarm; + SPLogLevelSetting =" @( + MSFT_SPLogLevelItem {TraceLevel="Default"; Name="Administration"; EventLevel="Default"; Area="Access Services"}, + MSFT_SPLogLevelItem {TraceLevel="Default"; Name="General"; EventLevel="Default"; Area="SharePoint Server"} + ); + } + +'@ + } + + It "Should return valid DSC block from the Export method" { + Export-TargetResource | Should -Be $result + } + } } } } diff --git a/tests/Unit/SharePointDsc/SharePointDsc.SPServiceAppPool.Tests.ps1 b/tests/Unit/SharePointDsc/SharePointDsc.SPServiceAppPool.Tests.ps1 index 7e82ba0ab..4d1f09741 100644 --- a/tests/Unit/SharePointDsc/SharePointDsc.SPServiceAppPool.Tests.ps1 +++ b/tests/Unit/SharePointDsc/SharePointDsc.SPServiceAppPool.Tests.ps1 @@ -50,7 +50,7 @@ try InModuleScope -ModuleName $script:DSCResourceFullName -ScriptBlock { Describe -Name $Global:SPDscHelper.DescribeHeader -Fixture { BeforeAll { - Invoke-Command -Scriptblock $Global:SPDscHelper.InitializeScript -NoNewScope + Invoke-Command -ScriptBlock $Global:SPDscHelper.InitializeScript -NoNewScope # Initialize tests @@ -225,7 +225,7 @@ try { Ensure = "Present"; Name = "SharePoint Service Applications"; - PsDscRunAsCredential = "$Credsspfarm"; + PsDscRunAsCredential = $Credsspfarm; ServiceAccount = "Demo\ServiceAccount"; } diff --git a/tests/Unit/SharePointDsc/SharePointDsc.SPWebApplication.Tests.ps1 b/tests/Unit/SharePointDsc/SharePointDsc.SPWebApplication.Tests.ps1 index 5f30da34b..45fbe381d 100644 --- a/tests/Unit/SharePointDsc/SharePointDsc.SPWebApplication.Tests.ps1 +++ b/tests/Unit/SharePointDsc/SharePointDsc.SPWebApplication.Tests.ps1 @@ -50,7 +50,7 @@ try InModuleScope -ModuleName $script:DSCResourceFullName -ScriptBlock { Describe -Name $Global:SPDscHelper.DescribeHeader -Fixture { BeforeAll { - Invoke-Command -Scriptblock $Global:SPDscHelper.InitializeScript -NoNewScope + Invoke-Command -ScriptBlock $Global:SPDscHelper.InitializeScript -NoNewScope # Initialize tests @@ -408,7 +408,6 @@ try } } - Context -Name "The web application does exist and should that uses Claims" -Fixture { BeforeAll { $testParams = @{ @@ -590,13 +589,13 @@ try It "Should return false from the test method" { Test-TargetResource @testParams | Should -Be $false } + It "Should call the new SPWebApplication cmdlet from the set method" { Set-TargetResource @testParams Assert-MockCalled New-SPWebApplication } } - Context -Name "The web application doesn't exist and shouldn't that uses Claims" -Fixture { BeforeAll { $testParams = @{ @@ -766,6 +765,136 @@ try } } + Context -Name "The web application does exist and should, but has incorrect settings" -Fixture { + BeforeAll { + $testParams = @{ + Name = "SharePoint Sites" + ApplicationPool = "SharePoint Web Apps" + ApplicationPoolAccount = "DEMO\ServiceAccount" + DatabaseName = "SP_Content_00" + WebAppUrl = "http://sites.sharepoint.com" + Ensure = "Present" + } + + try + { + [Microsoft.SharePoint.Administration.SPWebService] | Out-Null + } + catch + { + Add-Type -TypeDefinition @" + namespace Microsoft.SharePoint.Administration + { + public class SPWebService { + public SPWebService() { } + } + } +"@ + } + + try + { + [Microsoft.SharePoint.Administration.SPApplicationPool] | Out-Null + } + catch + { + Add-Type -TypeDefinition @" + namespace Microsoft.SharePoint.Administration + { + public class SPApplicationPool { + public SPApplicationPool(System.String account, System.Object service) { } + + public string CurrentIdentityType { get; set; } + public string Username { get; set; } + public void Update(bool force) { } + public void Provision() { } + } + } +"@ + } + + Mock -CommandName Get-SPAuthenticationProvider -MockWith { + return @{ + + DisplayName = "TestProvider" + LoginProviderName = "TestProvider" + ClaimProviderName = "TestClaimProvider" + AuthenticationRedirectUrl = "/_trust/default.aspx?trust=TestProvider" + } + } + + Mock -CommandName Get-SPWebApplication -MockWith { + $returnval = @(@{ + DisplayName = $testParams.Name + ApplicationPool = @{ + Name = "SharePoint Old AppPool" + Username = $testParams.ApplicationPoolAccount + } + UseClaimsAuthentication = $true + ContentDatabases = @( + @{ + Name = "SP_Content_01" + Server = "sql.domain.local" + } + ) + IisSettings = @( + @{ Path = "C:\inetpub\wwwroot\something" } + ) + Url = $testParams.WebAppUrl + } + ) + $returnval = $returnval | Add-Member -MemberType ScriptMethod ` + -Name Update ` + -Value { + $global:SPDscRanWebAppUpdate = $true + } -PassThru -Force | Add-Member -MemberType ScriptMethod ` + -Name ProvisionGlobally ` + -Value { + } -PassThru -Force + + return $returnVal + } + + Mock -CommandName Get-SPDscContentService -MockWith { + $returnVal = @{ + ApplicationPools = @( + @{ + Name = "SharePoint Old AppPool" + } + ) + } + $returnVal = $returnVal | Add-Member -MemberType ScriptMethod -Name Update -Value { + $Global:SPDscAntivirusUpdated = $true + } -PassThru + return $returnVal + } + + Mock -CommandName Get-SPManagedAccount -MockWith { + return "" + } + + Mock -CommandName Mount-SPContentDatabase -MockWith { } + } + + It "Should return present from the get method" { + $result = Get-TargetResource @testParams + $result.Ensure | Should -Be "Present" + $result.DatabaseName | Should -Be "SP_Content_01" + $result.ApplicationPool | Should -Be "SharePoint Old AppPool" + } + + It "Should return true from the test method" { + Test-TargetResource @testParams | Should -Be $false + } + + It "Should call the new SPWebApplication cmdlet from the set method" { + $global:SPDscRanWebAppUpdate = $false + Set-TargetResource @testParams + Assert-MockCalled Mount-SPContentDatabase + $global:SPDscRanWebAppUpdate | Should -Be $true + } + } + Context -Name "Running ReverseDsc Export" -Fixture { BeforeAll { Import-Module (Join-Path -Path (Split-Path -Path (Get-Module SharePointDsc -ListAvailable).Path -Parent) -ChildPath "Modules\SharePointDSC.Reverse\SharePointDSC.Reverse.psm1") From 92f8a9b621f7b22eab7e8055b58fe5b17570f2e2 Mon Sep 17 00:00:00 2001 From: Yorick Kuijs Date: Fri, 1 Oct 2021 22:16:12 +0200 Subject: [PATCH 2/2] Fix broken unit test --- .../SharePointDsc/SharePointDsc.SPSite.Tests.ps1 | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/Unit/SharePointDsc/SharePointDsc.SPSite.Tests.ps1 b/tests/Unit/SharePointDsc/SharePointDsc.SPSite.Tests.ps1 index 7b3147609..0549909e1 100644 --- a/tests/Unit/SharePointDsc/SharePointDsc.SPSite.Tests.ps1 +++ b/tests/Unit/SharePointDsc/SharePointDsc.SPSite.Tests.ps1 @@ -184,7 +184,18 @@ try $ArgumentList[1] -eq "CentralAdminSystemAccountUserToken" } - Mock -CommandName Get-SPSite -MockWith { return $null } + $global:SPDscGetSPSiteCalled = $false + Mock -CommandName Get-SPSite -MockWith { + if ($global:SPDscGetSPSiteCalled) + { + return "" + } + else + { + $global:SPDscGetSPSiteCalled = $true + return $null + } + } Mock -CommandName Start-Process -MockWith { return @{