DSCResources/MSFT_SPSearchContentSource/MSFT_SPSearchContentSource.psm1
function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [parameter(Mandatory = $true)] [System.String] $Name, [parameter(Mandatory = $true)] [System.String] $ServiceAppName, [parameter(Mandatory = $true)] [ValidateSet("SharePoint","Website","FileShare")] [System.String] $ContentSourceType, [parameter(Mandatory = $true)] [System.String[]] $Addresses, [parameter(Mandatory = $true)] [ValidateSet("CrawlEverything","CrawlFirstOnly","Custom")] [System.String] $CrawlSetting, [parameter(Mandatory = $false)] [System.Boolean] $ContinuousCrawl, [parameter(Mandatory = $false)] [Microsoft.Management.Infrastructure.CimInstance] $IncrementalSchedule, [parameter(Mandatory = $false)] [Microsoft.Management.Infrastructure.CimInstance] $FullSchedule, [parameter(Mandatory = $false)] [ValidateSet("Normal","High")] [System.String] $Priority, [parameter(Mandatory = $false)] [System.UInt32] $LimitPageDepth, [parameter(Mandatory = $false)] [System.UInt32] $LimitServerHops, [parameter(Mandatory = $false)] [ValidateSet("Present","Absent")] [System.String] $Ensure = "Present", [parameter(Mandatory = $false)] [System.Boolean] $Force, [parameter(Mandatory = $false)] [System.Management.Automation.PSCredential] $InstallAccount ) $result = Invoke-SPDSCCommand -Credential $InstallAccount -Arguments @($PSBoundParameters, $PSScriptRoot) -ScriptBlock { $params = $args[0] $ScriptRoot = $args[1] Import-Module (Join-Path $ScriptRoot "..\..\Modules\SharePointDsc.Search\SPSearchContentSource.Schedules.psm1" -Resolve) $source = Get-SPEnterpriseSearchCrawlContentSource -SearchApplication $params.ServiceAppName -Identity $params.Name -ErrorAction SilentlyContinue if ($null -eq $source) { return @{ Name = $params.Name ServiceAppName = $params.ServiceAppName ContentSourceType = $params.ContentSourceType Ensure = "Absent" } } switch ($source.Type) { "SharePoint" { $crawlSetting = "CrawlEverything" if ($source.SharePointCrawlBehavior -eq "CrawlSites") { $crawlSetting = "CrawlFirstOnly" } $result = @{ Name = $params.Name ServiceAppName = $params.ServiceAppName Ensure = "Present" ContentSourceType = "SharePoint" Addresses = $source.StartAddresses.AbsoluteUri CrawlSetting = $crawlSetting ContinuousCrawl = $source.EnableContinuousCrawls IncrementalSchedule = (Get-SPDSCSearchCrawlSchedule -Schedule $source.IncrementalCrawlSchedule) FullSchedule = (Get-SPDSCSearchCrawlSchedule -Schedule $source.FullCrawlSchedule) Priority = $source.CrawlPriority InstallAccount = $params.InstallAccount } } "Web" { $crawlSetting = "Custom" if ($source.MaxPageEnumerationDepth -eq [System.Int32]::MaxValue) { $crawlSetting = "CrawlEverything" } if ($source.MaxPageEnumerationDepth -eq 0) { $crawlSetting = "CrawlFirstOnly" } $result = @{ Name = $params.Name ServiceAppName = $params.ServiceAppName Ensure = "Present" ContentSourceType = "Website" Addresses = $source.StartAddresses.AbsoluteUri CrawlSetting = $crawlSetting IncrementalSchedule = (Get-SPDSCSearchCrawlSchedule -Schedule $source.IncrementalCrawlSchedule) FullSchedule = (Get-SPDSCSearchCrawlSchedule -Schedule $source.FullCrawlSchedule) LimitPageDepth = $source.MaxPageEnumerationDepth LimitServerHops = $source.MaxSiteEnumerationDepth Priority = $source.CrawlPriority } } "File" { $crawlSetting = "CrawlFirstOnly" if ($source.FollowDirectories -eq $true) { $crawlSetting = "CrawlEverything" } $result = @{ Name = $params.Name ServiceAppName = $params.ServiceAppName Ensure = "Present" ContentSourceType = "FileShare" Addresses = $source.StartAddresses.AbsoluteUri.Replace("file:///","\\").Replace("/", "\") CrawlSetting = $crawlSetting IncrementalSchedule = (Get-SPDSCSearchCrawlSchedule -Schedule $source.IncrementalCrawlSchedule) FullSchedule = (Get-SPDSCSearchCrawlSchedule -Schedule $source.FullCrawlSchedule) Priority = $source.CrawlPriority } } Default { throw "SharePointDsc does not currently support '$($source.Type)' content sources. Please use only 'SharePoint', 'FileShare' or 'Website'." } } return $result } return $result } function Set-TargetResource { [CmdletBinding()] param ( [parameter(Mandatory = $true)] [System.String] $Name, [parameter(Mandatory = $true)] [System.String] $ServiceAppName, [parameter(Mandatory = $true)] [ValidateSet("SharePoint","Website","FileShare")] [System.String] $ContentSourceType, [parameter(Mandatory = $true)] [System.String[]] $Addresses, [parameter(Mandatory = $true)] [ValidateSet("CrawlEverything","CrawlFirstOnly","Custom")] [System.String] $CrawlSetting, [parameter(Mandatory = $false)] [System.Boolean] $ContinuousCrawl, [parameter(Mandatory = $false)] [Microsoft.Management.Infrastructure.CimInstance] $IncrementalSchedule, [parameter(Mandatory = $false)] [Microsoft.Management.Infrastructure.CimInstance] $FullSchedule, [parameter(Mandatory = $false)] [ValidateSet("Normal","High")] [System.String] $Priority, [parameter(Mandatory = $false)] [System.UInt32] $LimitPageDepth, [parameter(Mandatory = $false)] [System.UInt32] $LimitServerHops, [parameter(Mandatory = $false)] [ValidateSet("Present","Absent")] [System.String] $Ensure = "Present", [parameter(Mandatory = $false)] [System.Boolean] $Force, [parameter(Mandatory = $false)] [System.Management.Automation.PSCredential] $InstallAccount ) switch ($ContentSourceType) { "SharePoint" { if ($PSBoundParameters.ContainsKey("LimitPageDepth") -eq $true) { throw "Parameter LimitPageDepth is not valid for SharePoint content sources" } if ($PSBoundParameters.ContainsKey("LimitServerHops") -eq $true) { throw "Parameter LimitServerHops is not valid for SharePoint content sources" } if ($ContinuousCrawl -eq $true -and $PSBoundParameters.ContainsKey("IncrementalSchedule") -eq $true) { throw "You can not specify an incremental crawl schedule on a content source that will use continous crawl" } if ($CrawlSetting -eq "Custom") { throw "Parameter 'CrawlSetting' can only be set to custom for website content sources" } } "Website" { if ($PSBoundParameters.ContainsKey("ContinuousCrawl") -eq $true) { throw "Parameter ContinuousCrawl is not valid for website content sources" } if ($PSBoundParameters.ContainsKey("LimitServerHops") -eq $true) { throw "Parameter LimitServerHops is not valid for website content sources" } } "FileShare" { if ($PSBoundParameters.ContainsKey("LimitPageDepth") -eq $true) { throw "Parameter LimitPageDepth is not valid for file share content sources" } if ($PSBoundParameters.ContainsKey("LimitServerHops") -eq $true) { throw "Parameter LimitServerHops is not valid for file share content sources" } if ($CrawlSetting -eq "Custom") { throw "Parameter 'CrawlSetting' can only be set to custom for website content sources" } } } $CurrentValues = Get-TargetResource @PSBoundParameters if ($ContentSourceType -ne $CurrentValues.ContentSourceType -and $Force -eq $false) { throw "The type of the a search content source can not be changed from '$($CurrentValues.ContentSourceType)' to '$ContentSourceType' without deleting and adding it again. Specify 'Force = `$true' in order to allow DSC to do this, or manually remove the existing content source and re-run the configuration." } if (($ContentSourceType -ne $CurrentValues.ContentSourceType -and $Force -eq $true) -or ($Ensure -eq "Absent" -and $CurrentValues.Ensure -ne $Ensure)) { # Remove the existing content source Invoke-SPDSCCommand -Credential $InstallAccount -Arguments @($PSBoundParameters) -ScriptBlock { $params = $args[0] Remove-SPEnterpriseSearchCrawlContentSource -Identity $params.Name -SearchApplication $params.ServiceAppName -Confirm:$false } } if ($Ensure -eq "Present") { # Create the new content source and then apply settings to it Invoke-SPDSCCommand -Credential $InstallAccount -Arguments @($PSBoundParameters) -ScriptBlock { $params = $args[0] $OFS = "," $startAddresses = "$($params.Addresses)" $source = Get-SPEnterpriseSearchCrawlContentSource -SearchApplication $params.ServiceAppName -Identity $params.Name -ErrorAction SilentlyContinue if ($null -eq $source) { switch ($params.ContentSourceType) { "SharePoint" { $newType = "SharePoint" } "Website" { $newType = "Web" } "FileShare" { $newType = "File" } } $source = New-SPEnterpriseSearchCrawlContentSource -SearchApplication $params.ServiceAppName -Type $newType -name $params.Name -StartAddresses $startAddresses } $allSetArguments = @{ Identity = $params.Name SearchApplication = $params.ServiceAppName Confirm = $false } if ($params.ContentSourceType -eq "SharePoint" -and $source.EnableContinuousCrawls -eq $true) { Set-SPEnterpriseSearchCrawlContentSource @allSetArguments -EnableContinuousCrawls $false Write-Verbose -Message "Pausing to allow Continuous Crawl to shut down correctly before continuing updating the configuration." Start-Sleep -Seconds 300 } if ($source.CrawlStatus -ne "Idle") { Write-Verbose "Content source '$($params.Name)' is not idle, stopping current crawls to allow settings to be updated" $source = Get-SPEnterpriseSearchCrawlContentSource -SearchApplication $params.ServiceAppName -Identity $params.Name $source.StopCrawl() $loopCount = 0 $sourceToWait = Get-SPEnterpriseSearchCrawlContentSource -SearchApplication $params.ServiceAppName -Identity $params.Name while ($sourceToWait.CrawlStatus -ne "Idle" -or $loopCount > 15) { $sourceToWait = Get-SPEnterpriseSearchCrawlContentSource -SearchApplication $params.ServiceAppName -Identity $params.Name Write-Verbose "$([DateTime]::Now.ToShortTimeString()) - Waiting for content source '$($params.Name)' to be idle (waited $loopCount of 15 minutes)" Start-Sleep -Seconds 60 $loopCount++ } } $primarySetArgs = @{ StartAddresses = $startAddresses } if ($params.ContainsKey("ContinuousCrawl") -eq $true) { $primarySetArgs.Add("EnableContinuousCrawls", $params.ContinuousCrawl) } if ($params.ContainsKey("Priority") -eq $true) { switch ($params.Priority) { "High" { $primarySetArgs.Add("CrawlPriority", "2") } "Normal" { $primarySetArgs.Add("CrawlPriority", "1") } } } Set-SPEnterpriseSearchCrawlContentSource @allSetArguments @primarySetArgs # Set the incremental search values if ($params.ContainsKey("IncrementalSchedule") -eq $true -and $null -ne $params.IncrementalSchedule) { $incrementalSetArgs = @{ ScheduleType = "Incremental" } switch ($params.IncrementalSchedule.ScheduleType) { "None" { $incrementalSetArgs.Add("RemoveCrawlSchedule", $true) } "Daily" { $incrementalSetArgs.Add("DailyCrawlSchedule", $true) } "Weekly" { $incrementalSetArgs.Add("WeeklyCrawlSchedule", $true) if ((Test-SPDSCObjectHasProperty -Object $params.IncrementalSchedule -PropertyName "CrawlScheduleDaysOfWeek") -eq $true) { $OFS = "," $incrementalSetArgs.Add("CrawlScheduleDaysOfWeek", [enum]::Parse([Microsoft.Office.Server.Search.Administration.DaysOfWeek], "$($params.IncrementalSchedule.CrawlScheduleDaysOfWeek)")) } } "Monthly" { $incrementalSetArgs.Add("MonthlyCrawlSchedule", $true) if ((Test-SPDSCObjectHasProperty -Object $params.IncrementalSchedule -PropertyName "CrawlScheduleDaysOfMonth") -eq $true) { $incrementalSetArgs.Add("CrawlScheduleDaysOfMonth", $params.IncrementalSchedule.CrawlScheduleDaysOfMonth) } if ((Test-SPDSCObjectHasProperty -Object $params.IncrementalSchedule -PropertyName "CrawlScheduleMonthsOfYear") -eq $true) { foreach ($month in $params.IncrementalSchedule.CrawlScheduleMonthsOfYear) { $months += [Microsoft.Office.Server.Search.Administration.MonthsOfYear]::$month } $incrementalSetArgs.Add("CrawlScheduleMonthsOfYear", $months) } } } if ((Test-SPDSCObjectHasProperty -Object $params.IncrementalSchedule -PropertyName "CrawlScheduleRepeatDuration") -eq $true) { $incrementalSetArgs.Add("CrawlScheduleRepeatDuration", $params.IncrementalSchedule.CrawlScheduleRepeatDuration) } if ((Test-SPDSCObjectHasProperty -Object $params.IncrementalSchedule -PropertyName "CrawlScheduleRepeatInterval") -eq $true) { $incrementalSetArgs.Add("CrawlScheduleRepeatInterval", $params.IncrementalSchedule.CrawlScheduleRepeatInterval) } if ((Test-SPDSCObjectHasProperty -Object $params.IncrementalSchedule -PropertyName "CrawlScheduleRunEveryInterval") -eq $true) { $incrementalSetArgs.Add("CrawlScheduleRunEveryInterval", $params.IncrementalSchedule.CrawlScheduleRunEveryInterval) } Set-SPEnterpriseSearchCrawlContentSource @allSetArguments @incrementalSetArgs } # Set the full search values if ($params.ContainsKey("FullSchedule") -eq $true) { $fullSetArgs = @{ ScheduleType = "Full" } switch ($params.FullSchedule.ScheduleType) { "None" { $fullSetArgs.Add("RemoveCrawlSchedule", $true) } "Daily" { $fullSetArgs.Add("DailyCrawlSchedule", $true) } "Weekly" { $fullSetArgs.Add("WeeklyCrawlSchedule", $true) if ((Test-SPDSCObjectHasProperty -Object $params.FullSchedule -PropertyName "CrawlScheduleDaysOfWeek") -eq $true) { foreach ($day in $params.FullSchedule.CrawlScheduleDaysOfWeek) { $daysOfweek += [Microsoft.Office.Server.Search.Administration.DaysOfWeek]::$day } $fullSetArgs.Add("CrawlScheduleDaysOfWeek", $daysOfweek) } } "Monthly" { $fullSetArgs.Add("MonthlyCrawlSchedule", $true) if ((Test-SPDSCObjectHasProperty -Object $params.FullSchedule -PropertyName "CrawlScheduleDaysOfMonth") -eq $true) { $fullSetArgs.Add("CrawlScheduleDaysOfMonth", $params.FullSchedule.CrawlScheduleDaysOfMonth) } if ((Test-SPDSCObjectHasProperty -Object $params.FullSchedule -PropertyName "CrawlScheduleMonthsOfYear") -eq $true) { foreach ($month in $params.FullSchedule.CrawlScheduleMonthsOfYear) { $months += [Microsoft.Office.Server.Search.Administration.MonthsOfYear]::$month } $fullSetArgs.Add("CrawlScheduleMonthsOfYear", $months) } } } if ((Test-SPDSCObjectHasProperty -Object $params.FullSchedule -PropertyName "CrawlScheduleRepeatDuration") -eq $true) { $fullSetArgs.Add("CrawlScheduleRepeatDuration", $params.FullSchedule.CrawlScheduleRepeatDuration) } if ((Test-SPDSCObjectHasProperty -Object $params.FullSchedule -PropertyName "CrawlScheduleRepeatInterval") -eq $true) { $fullSetArgs.Add("CrawlScheduleRepeatInterval", $params.FullSchedule.CrawlScheduleRepeatInterval) } if ((Test-SPDSCObjectHasProperty -Object $params.FullSchedule -PropertyName "CrawlScheduleRunEveryInterval") -eq $true) { $fullSetArgs.Add("CrawlScheduleRunEveryInterval", $params.FullSchedule.CrawlScheduleRunEveryInterval) } Set-SPEnterpriseSearchCrawlContentSource @allSetArguments @fullSetArgs } } } } function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( [parameter(Mandatory = $true)] [System.String] $Name, [parameter(Mandatory = $true)] [System.String] $ServiceAppName, [parameter(Mandatory = $true)] [ValidateSet("SharePoint","Website","FileShare")] [System.String] $ContentSourceType, [parameter(Mandatory = $true)] [System.String[]] $Addresses, [parameter(Mandatory = $true)] [ValidateSet("CrawlEverything","CrawlFirstOnly","Custom")] [System.String] $CrawlSetting, [parameter(Mandatory = $false)] [System.Boolean] $ContinuousCrawl, [parameter(Mandatory = $false)] [Microsoft.Management.Infrastructure.CimInstance] $IncrementalSchedule, [parameter(Mandatory = $false)] [Microsoft.Management.Infrastructure.CimInstance] $FullSchedule, [parameter(Mandatory = $false)] [ValidateSet("Normal","High")] [System.String] $Priority, [parameter(Mandatory = $false)] [System.UInt32] $LimitPageDepth, [parameter(Mandatory = $false)] [System.UInt32] $LimitServerHops, [parameter(Mandatory = $false)] [ValidateSet("Present","Absent")] [System.String] $Ensure = "Present", [parameter(Mandatory = $false)] [System.Boolean] $Force, [parameter(Mandatory = $false)] [System.Management.Automation.PSCredential] $InstallAccount ) switch ($ContentSourceType) { "SharePoint" { if ($PSBoundParameters.ContainsKey("LimitPageDepth") -eq $true) { throw "Parameter LimitPageDepth is not valid for SharePoint content sources" } if ($PSBoundParameters.ContainsKey("LimitServerHops") -eq $true) { throw "Parameter LimitServerHops is not valid for SharePoint content sources" } if ($ContinuousCrawl -eq $true -and $PSBoundParameters.ContainsKey("IncrementalSchedule") -eq $true) { throw "You can not specify an incremental crawl schedule on a content source that will use continous crawl" } if ($CrawlSetting -eq "Custom") { throw "Parameter 'CrawlSetting' can only be set to custom for website content sources" } } "Website" { if ($PSBoundParameters.ContainsKey("ContinuousCrawl") -eq $true) { throw "Parameter ContinuousCrawl is not valid for website content sources" } if ($PSBoundParameters.ContainsKey("LimitServerHops") -eq $true) { throw "Parameter LimitServerHops is not valid for website content sources" } } "FileShare" { if ($PSBoundParameters.ContainsKey("LimitPageDepth") -eq $true) { throw "Parameter LimitPageDepth is not valid for file share content sources" } if ($PSBoundParameters.ContainsKey("LimitServerHops") -eq $true) { throw "Parameter LimitServerHops is not valid for file share content sources" } if ($CrawlSetting -eq "Custom") { throw "Parameter 'CrawlSetting' can only be set to custom for website content sources" } } } $CurrentValues = Get-TargetResource @PSBoundParameters $PSBoundParameters.Ensure = $Ensure if ($Ensure -eq "Absent") { return Test-SPDscParameterState -CurrentValues $CurrentValues ` -DesiredValues $PSBoundParameters ` -ValuesToCheck @("Ensure") } Import-Module (Join-Path $PSScriptRoot "..\..\Modules\SharePointDsc.Search\SPSearchContentSource.Schedules.psm1" -Resolve) if (($PSBoundParameters.ContainsKey("IncrementalSchedule") -eq $true) -and ($null -ne $IncrementalSchedule) -and ((Test-SPDSCSearchCrawlSchedule -CurrentSchedule $CurrentValues.IncrementalSchedule -DesiredSchedule $IncrementalSchedule) -eq $false)) { return $false; } if (($PSBoundParameters.ContainsKey("FullSchedule") -eq $true) -and ($null -ne $FullSchedule) -and ((Test-SPDSCSearchCrawlSchedule -CurrentSchedule $CurrentValues.FullSchedule -DesiredSchedule $FullSchedule) -eq $false)) { return $false; } # Compare the addresses as Uri objects to handle things like trailing /'s on URLs $currentAddresses = @() foreach ($address in $CurrentValues.Addresses) { $currentAddresses += New-Object System.Uri -ArgumentList $address } $desiredAddresses = @() foreach ($address in $Addresses) { $desiredAddresses += New-Object System.Uri -ArgumentList $address } if ($null -ne (Compare-Object -ReferenceObject $currentAddresses -DifferenceObject $desiredAddresses)) { return $false } return Test-SPDscParameterState -CurrentValues $CurrentValues ` -DesiredValues $PSBoundParameters ` -ValuesToCheck @("ContentSourceType", "CrawlSetting", "ContinousCrawl", "Priority", "LimitPageDepth", "LimitServerHops", "Ensure") } Export-ModuleMember -Function *-TargetResource |