diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a5b9d4b8..a981c97fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- SPUsageDefinition + - New resource + ## [4.6.0] - 2021-04-02 ### Added diff --git a/SharePointDsc/DSCResources/MSFT_SPUsageDefinition/MSFT_SPUsageDefinition.psm1 b/SharePointDsc/DSCResources/MSFT_SPUsageDefinition/MSFT_SPUsageDefinition.psm1 new file mode 100644 index 000000000..8ac845275 --- /dev/null +++ b/SharePointDsc/DSCResources/MSFT_SPUsageDefinition/MSFT_SPUsageDefinition.psm1 @@ -0,0 +1,308 @@ +$script:SPDscUtilModulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\Modules\SharePointDsc.Util' +Import-Module -Name $script:SPDscUtilModulePath + +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter()] + [ValidateRange(1, 31)] + [System.UInt32] + $DaysRetained, + + [Parameter()] + [System.UInt32] + $DaysToKeepUsageFiles, + + [Parameter()] + [System.UInt64] + $MaxTotalSizeInBytes, + + [Parameter()] + [System.Boolean] + $Enabled, + + [Parameter()] + [System.Boolean] + $UsageDatabaseEnabled, + + [Parameter()] + [ValidateSet("Present", "Absent")] + [System.String] + $Ensure = "Present", + + [Parameter()] + [System.Management.Automation.PSCredential] + $InstallAccount + ) + + Write-Verbose -Message "Getting configuration for Usage Definition {$Name}" + + $result = Invoke-SPDscCommand -Credential $InstallAccount ` + -Arguments $PSBoundParameters ` + -ScriptBlock { + $params = $args[0] + + $usageDefinition = Get-SPUsageDefinition -Identity $params.Name + $nullReturn = @{ + Name = $params.Name + DaysRetained = $params.DaysRetained + DaysToKeepUsageFiles = $params.DaysToKeepUsageFiles + MaxTotalSizeInBytes = $params.MaxTotalSizeInBytes + Enabled = $params.Enabled + UsageDatabaseEnabled = $params.UsageDatabaseEnabled + Ensure = "Absent" + } + if ($null -eq $usageDefinition) + { + return $nullReturn + } + + return @{ + Name = $params.Name + DaysRetained = $usageDefinition.Retention + DaysToKeepUsageFiles = $usageDefinition.DaysToKeepUsageFiles + MaxTotalSizeInBytes = $usageDefinition.MaxTotalSizeInBytes + Enabled = $usageDefinition.Enabled + UsageDatabaseEnabled = $usageDefinition.UsageDatabaseEnabled + Ensure = "Present" + } + } + return $result +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter()] + [ValidateRange(1, 31)] + [System.UInt32] + $DaysRetained, + + [Parameter()] + [System.UInt32] + $DaysToKeepUsageFiles, + + [Parameter()] + [System.UInt64] + $MaxTotalSizeInBytes, + + [Parameter()] + [System.Boolean] + $Enabled, + + [Parameter()] + [System.Boolean] + $UsageDatabaseEnabled, + + [Parameter()] + [ValidateSet("Present", "Absent")] + [System.String] + $Ensure = "Present", + + [Parameter()] + [System.Management.Automation.PSCredential] + $InstallAccount + ) + + Write-Verbose -Message "Setting configuration for Usage Definition {$Name}" + + if ($Ensure -eq "Absent") + { + $message = "This resource cannot remove a Usage Definition. Please use ensure equals Present." + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $MyInvocation.MyCommand.Source + throw $message + } + + if ($PSBoundParameters.ContainsKey("DaysRetained") -eq $false -and ` + $PSBoundParameters.ContainsKey("DaysToKeepUsageFiles") -eq $false -and ` + $PSBoundParameters.ContainsKey("MaxTotalSizeInBytes") -eq $false -and ` + $PSBoundParameters.ContainsKey("Enabled") -eq $false -and ` + $PSBoundParameters.ContainsKey("UsageDatabaseEnabled") -eq $false) + { + $message = ("You have to at least specify one parameter: DaysRetained, DaysToKeepUsageFiles, " + ` + "MaxTotalSizeInBytes, Enabled or UsageDatabaseEnabled.") + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $MyInvocation.MyCommand.Source + throw $message + } + + if ((Get-SPDscInstalledProductVersion).FileMajorPart -eq 15 -and ` + $PSBoundParameters.ContainsKey("UsageDatabaseEnabled") -eq $true) + { + $message = ("Parameter UsageDatabaseEnabled not supported in SharePoint 2013. Please " + ` + "remove it from the configuration.") + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $MyInvocation.MyCommand.Source + throw $message + } + + Invoke-SPDscCommand -Credential $InstallAccount ` + -Arguments @($PSBoundParameters, $MyInvocation.MyCommand.Source) ` + -ScriptBlock { + $params = $args[0] + $eventSource = $args[1] + + $usageDefinition = Get-SPUsageDefinition -Identity $params.Name + + if ($null -eq $usageDefinition) + { + $message = "The specified Usage Definition {" + $params.Name + "} could not be found." + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $eventSource + throw $message + } + + $newParams = @{ + Identity = $params.Name + } + + if ($params.ContainsKey("DaysRetained")) + { + $newParams.DaysRetained = $params.DaysRetained + } + + if ($params.ContainsKey("DaysToKeepUsageFiles")) + { + $newParams.DaysToKeepUsageFiles = $params.DaysToKeepUsageFiles + } + + if ($params.ContainsKey("MaxTotalSizeInBytes")) + { + $newParams.MaxTotalSizeInBytes = $params.MaxTotalSizeInBytes + } + + if ($params.ContainsKey("Enabled")) + { + $newParams.Enable = $params.Enabled + } + + if ($params.ContainsKey("UsageDatabaseEnabled")) + { + $newParams.UsageDatabaseEnabled = $params.UsageDatabaseEnabled + } + + Set-SPUsageDefinition @newParams + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter()] + [ValidateRange(1, 31)] + [System.UInt32] + $DaysRetained, + + [Parameter()] + [System.UInt32] + $DaysToKeepUsageFiles, + + [Parameter()] + [System.UInt64] + $MaxTotalSizeInBytes, + + [Parameter()] + [System.Boolean] + $Enabled, + + [Parameter()] + [System.Boolean] + $UsageDatabaseEnabled, + + [Parameter()] + [ValidateSet("Present", "Absent")] + [System.String] + $Ensure = "Present", + + [Parameter()] + [System.Management.Automation.PSCredential] + $InstallAccount + ) + + Write-Verbose -Message "Testing configuration for Usage Definition {$Name}" + + $PSBoundParameters.Ensure = $Ensure + + $CurrentValues = Get-TargetResource @PSBoundParameters + + Write-Verbose -Message "Current Values: $(Convert-SPDscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-SPDscHashtableToString -Hashtable $PSBoundParameters)" + + $result = Test-SPDscParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck @("Ensure", + "Name", + "DaysRetained", + "DaysToKeepUsageFiles", + "MaxTotalSizeInBytes", + "Enabled", + "UsageDatabaseEnabled" + ) + + Write-Verbose -Message "Test-TargetResource returned $result" + + return $result +} + +function Export-TargetResource +{ + $VerbosePreference = "SilentlyContinue" + $ParentModuleBase = Get-Module "SharePointDsc" -ListAvailable | Select-Object -ExpandProperty Modulebase + $module = Join-Path -Path $ParentModuleBase -ChildPath "\DSCResources\MSFT_SPUsageDefinition\MSFT_SPUsageDefinition.psm1" -Resolve + + $Content = '' + $params = Get-DSCFakeParameters -ModulePath $module + + $usageDefinitions = Get-SPUsageDefinition + foreach ($usageDefinition in $usageDefinitions) + { + $PartialContent = " SPUsageDefinition UsageDefinition_" + $($usageDefinition.Name -replace " ", '') + "`r`n" + $PartialContent += " {`r`n" + $params.Name = $usageDefinition.Name + $params.Ensure = "Present" + $results = Get-TargetResource @params + + $results = Repair-Credentials -results $results + + $currentBlock = Get-DSCBlock -Params $results -ModulePath $module + $currentBlock = Convert-DSCStringParamToVariable -DSCBlock $currentBlock -ParameterName "PsDscRunAsCredential" + + $PartialContent += $currentBlock + $PartialContent += " }`r`n" + $Content += $PartialContent + } + + return $Content +} + +Export-ModuleMember -Function *-TargetResource diff --git a/SharePointDsc/DSCResources/MSFT_SPUsageDefinition/MSFT_SPUsageDefinition.schema.mof b/SharePointDsc/DSCResources/MSFT_SPUsageDefinition/MSFT_SPUsageDefinition.schema.mof new file mode 100644 index 000000000..5b098d43f --- /dev/null +++ b/SharePointDsc/DSCResources/MSFT_SPUsageDefinition/MSFT_SPUsageDefinition.schema.mof @@ -0,0 +1,12 @@ +[ClassVersion("1.0.0.0"), FriendlyName("SPUsageDefinition")] +class MSFT_SPUsageDefinition : OMI_BaseResource +{ + [Key, Description("Name of the Usage Definition to configure")] string Name; + [Write, Description("The number of days that usage is retained")] Uint32 DaysRetained; + [Write, Description("The number of days to keep usage file retention")] Uint32 DaysToKeepUsageFiles; + [Write, Description("Sets the maximum retention size in bytes")] Uint64 MaxTotalSizeInBytes; + [Write, Description("True enables the Usage Definition")] Boolean Enabled; + [Write, Description("True enables logging to the Usage database(SP2016 and above only)")] Boolean UsageDatabaseEnabled; + [Write, Description("Present to configure the diagnostics provider"), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; + [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_SPUsageDefinition/readme.md b/SharePointDsc/DSCResources/MSFT_SPUsageDefinition/readme.md new file mode 100644 index 000000000..664294b0b --- /dev/null +++ b/SharePointDsc/DSCResources/MSFT_SPUsageDefinition/readme.md @@ -0,0 +1,11 @@ +# Description + +**Type:** Distributed +**Requires CredSSP:** No + +This resource is responsible for configuring the Usage Definitions within +the local SharePoint farm. Using Ensure=Absent is not supported. +This resource can only apply configuration, not ensure they don't exist. + +To get an overview of all available Diagnostics Providers, use the cmdlet +Get-SPUsageDefinition. diff --git a/SharePointDsc/Examples/Resources/SPUsageDefinition/1-Configure.ps1 b/SharePointDsc/Examples/Resources/SPUsageDefinition/1-Configure.ps1 new file mode 100644 index 000000000..b4d3fd3c1 --- /dev/null +++ b/SharePointDsc/Examples/Resources/SPUsageDefinition/1-Configure.ps1 @@ -0,0 +1,66 @@ + +<#PSScriptInfo + +.VERSION 1.0.0 + +.GUID 80d306fa-8bd4-4a8d-9f7a-bf40df95e661 + +.AUTHOR DSC Community + +.COMPANYNAME DSC Community + +.COPYRIGHT DSC Community contributors. All rights reserved. + +.TAGS + +.LICENSEURI https://github.com/dsccommunity/SharePointDsc/blob/master/LICENSE + +.PROJECTURI https://github.com/dsccommunity/SharePointDsc + +.ICONURI https://dsccommunity.org/images/DSC_Logo_300p.png + +.EXTERNALMODULEDEPENDENCIES + +.REQUIREDSCRIPTS + +.EXTERNALSCRIPTDEPENDENCIES + +.RELEASENOTES +Updated author, copyright notice, and URLs. + +.PRIVATEDATA + +#> + +<# + +.DESCRIPTION + This example shows how to configure the Administrative Actions Usage Definition. + +#> + +Configuration Example +{ + param + ( + [Parameter(Mandatory = $true)] + [PSCredential] + $SetupAccount + ) + + Import-DscResource -ModuleName SharePointDsc + + node localhost + { + SPUsageDefinition 'AdministrativeActions' + { + Name = "Administrative Actions" + DaysRetained = 14 + DaysToKeepUsageFiles = 1 + MaxTotalSizeInBytes = 10000000000000 + Enabled = $true + UsageDatabaseEnabled = $true + PSDscRunAsCredential = $SetupAccount + } + } +} diff --git a/tests/Unit/SharePointDsc/SharePointDsc.SPUsageDefinition.Tests.ps1 b/tests/Unit/SharePointDsc/SharePointDsc.SPUsageDefinition.Tests.ps1 new file mode 100644 index 000000000..e01062c9b --- /dev/null +++ b/tests/Unit/SharePointDsc/SharePointDsc.SPUsageDefinition.Tests.ps1 @@ -0,0 +1,298 @@ +[CmdletBinding()] +param +( + [Parameter()] + [string] + $SharePointCmdletModule = (Join-Path -Path $PSScriptRoot ` + -ChildPath "..\Stubs\SharePoint\15.0.4805.1000\Microsoft.SharePoint.PowerShell.psm1" ` + -Resolve) +) + +$script:DSCModuleName = 'SharePointDsc' +$script:DSCResourceName = 'SPUsageDefinition' +$script:DSCResourceFullName = 'MSFT_' + $script:DSCResourceName + +function Invoke-TestSetup +{ + try + { + Import-Module -Name DscResource.Test -Force + + Import-Module -Name (Join-Path -Path $PSScriptRoot ` + -ChildPath "..\UnitTestHelper.psm1" ` + -Resolve) + + $Global:SPDscHelper = New-SPDscUnitTestHelper -SharePointStubModule $SharePointCmdletModule ` + -DscResource $script:DSCResourceName + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + } + + $script:testEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:DSCModuleName ` + -DSCResourceName $script:DSCResourceFullName ` + -ResourceType 'Mof' ` + -TestType 'Unit' +} + +function Invoke-TestCleanup +{ + Restore-TestEnvironment -TestEnvironment $script:testEnvironment +} + +Invoke-TestSetup + +try +{ + InModuleScope -ModuleName $script:DSCResourceFullName -ScriptBlock { + Describe -Name $Global:SPDscHelper.DescribeHeader -Fixture { + BeforeAll { + Invoke-Command -ScriptBlock $Global:SPDscHelper.InitializeScript -NoNewScope + + Mock -CommandName Get-SPUsageDefinition -MockWith { + return @{ + Name = "Administrative Actions" + Retention = 14 + DaysToKeepUsageFiles = 1 + MaxTotalSizeInBytes = 10000000000000 + Enabled = $true + UsageDatabaseEnabled = $true + } + } + + Mock -CommandName Set-SPUsageDefinition -MockWith { } + + function Add-SPDscEvent + { + param ( + [Parameter(Mandatory = $true)] + [System.String] + $Message, + + [Parameter(Mandatory = $true)] + [System.String] + $Source, + + [Parameter()] + [ValidateSet('Error', 'Information', 'FailureAudit', 'SuccessAudit', 'Warning')] + [System.String] + $EntryType, + + [Parameter()] + [System.UInt32] + $EventID + ) + } + } + + Context -Name "When the Usage Definition passed doesn't exist" -Fixture { + BeforeAll { + $testParams = @{ + Name = "MyFakeProvider" + DaysRetained = 14 + DaysToKeepUsageFiles = 1 + MaxTotalSizeInBytes = 10000000000000 + Enabled = $true + Ensure = "Present" + } + + if ($Global:SPDscHelper.CurrentStubBuildNumber.Major -ne 15) + { + $testParams.UsageDatabaseEnabled = $true + } + + Mock -CommandName Get-SPUsageDefinition -MockWith { return $null } + } + + It "Should return false when the Test method is called" { + Test-TargetResource @testParams | Should -Be $false + } + + It "Should throw an error about a non-existing definition" { + { Set-TargetResource @testParams } | Should -Throw ("The specified Usage Definition {" + $testParams.Name + "} could not be found.") + } + + It "Should return absent from the Get method" { + (Get-TargetResource @testParams).Ensure | Should -Be "Absent" + } + } + + Context -Name "When the Usage Definition passed doesn't exist" -Fixture { + BeforeAll { + $testParams = @{ + Name = "Administrative Actions" + } + } + + It "Should throw an error about having to specify a parameter" { + { Set-TargetResource @testParams } | Should -Throw "You have to at least specify one parameter: DaysRetained, DaysToKeepUsageFiles, MaxTotalSizeInBytes, Enabled or UsageDatabaseEnabled." + } + } + + if ($Global:SPDscHelper.CurrentStubBuildNumber.Major -eq 15) + { + Context -Name "When the parameter UsageDatabaseEnabled is passed for SharePoint 2013" -Fixture { + BeforeAll { + $testParams = @{ + Name = "Administrative Actions" + DaysRetained = 14 + DaysToKeepUsageFiles = 1 + MaxTotalSizeInBytes = 10000000000000 + Enabled = $true + UsageDatabaseEnabled = $true + Ensure = "Present" + } + } + + It "Should throw an error about a the incorrect use of the parameter" { + { Set-TargetResource @testParams } | Should -Throw "Parameter UsageDatabaseEnabled not supported in SharePoint 2013. Please remove it from the configuration." + } + } + } + + Context -Name "When the Usage Definition exists, but has incorrect settings" -Fixture { + BeforeAll { + $testParams = @{ + Name = "Administrative Actions" + DaysRetained = 13 + DaysToKeepUsageFiles = 2 + MaxTotalSizeInBytes = 20000000000000 + Enabled = $false + Ensure = "Present" + } + + if ($Global:SPDscHelper.CurrentStubBuildNumber.Major -ne 15) + { + $testParams.UsageDatabaseEnabled = $false + } + } + + It "Should return false when the Test method is called" { + Test-TargetResource @testParams | Should -Be $false + } + + It "Should properly configure the provider" { + Set-TargetResource @testParams + Assert-MockCalled Set-SPUsageDefinition + } + + It "Should return a DaysRetained of 14 from the Get method" { + (Get-TargetResource @testParams).DaysRetained | Should -Be 14 + } + } + + Context -Name "When the Usage Definition exists and has correct settings" -Fixture { + BeforeAll { + $testParams = @{ + Name = "Administrative Actions" + DaysRetained = 14 + DaysToKeepUsageFiles = 1 + MaxTotalSizeInBytes = 10000000000000 + Enabled = $true + Ensure = "Present" + } + + if ($Global:SPDscHelper.CurrentStubBuildNumber.Major -ne 15) + { + $testParams.UsageDatabaseEnabled = $true + } + } + + It "Should return true when the Test method is called" { + Test-TargetResource @testParams | Should -Be $true + } + + It "Should return a DaysRetained of 14 from the Get method" { + (Get-TargetResource @testParams).DaysRetained | Should -Be 14 + } + } + + Context -Name "When using Ensure is Absent" -Fixture { + BeforeAll { + $testParams = @{ + Name = "Administrative Actions" + DaysRetained = 14 + DaysToKeepUsageFiles = 1 + MaxTotalSizeInBytes = 10000000000000 + Enabled = $true + Ensure = "Absent" + } + + if ($Global:SPDscHelper.CurrentStubBuildNumber.Major -ne 15) + { + $testParams.UsageDatabaseEnabled = $false + } + } + + It "Should throw an exception in the set method" { + { Set-TargetResource @testParams } | Should -Throw "This resource cannot remove a Usage Definition. Please use ensure equals Present." + } + } + + 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 { + return @{ + Name = "Administrative Actions" + DaysRetained = 14 + DaysToKeepUsageFiles = 1 + MaxTotalSizeInBytes = 10000000000000 + Enabled = $true + Ensure = "Present" + } + } + + 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 = @' + SPUsageDefinition UsageDefinition_AdministrativeActions + { + DaysRetained = 14; + DaysToKeepUsageFiles = 1; + Enabled = $True; + Ensure = "Present"; + MaxTotalSizeInBytes = 10000000000000; + Name = "Administrative Actions"; + PsDscRunAsCredential = $Credsspfarm; + } + +'@ + } + + It "Should return valid DSC block from the Export method" { + Export-TargetResource | Should -Be $result + } + } + } + } +} +finally +{ + Invoke-TestCleanup +}