diff --git a/CHANGELOG.md b/CHANGELOG.md index 72ef636a2..31ab241fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 help for more information): - `Assert-SetupActionProperties` - `Invoke-SetupAction` + - `ConvertTo-ManagedServiceType` + - `ConvertFrom-ManagedServiceType` + - `Assert-ManagedServiceType` - The following public functions were added to the module (see comment-based help for more information): - `Install-SqlDscServer` @@ -60,6 +63,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `Complete-SqlDscFailoverCluster` - `Initialize-SqlDscRebuildDatabase` - `Import-SqlDscPreferredModule` + - `Get-SqlDscManagedComputer` + - `Get-SqlDscManagedComputerService` + - `Get-SqlDscTraceFlag` + - `Add-SqlDscTraceFlag` + - `Remove-SqlDscTraceFlag` + - `Set-SqlDscTraceFlag` + - `Get-SqlDscStartupParameter` + - `Set-SqlDscStartupParameter` + - Added class `StartupParameters` which can parse the startup parameters + of a manged computer service object. - New GitHub issue templates for proposing new public commands, proposing an enhancement to an existing command, or having a problem with an existing command. diff --git a/source/Classes/004.StartupParameters.ps1 b/source/Classes/004.StartupParameters.ps1 new file mode 100644 index 000000000..eca737fec --- /dev/null +++ b/source/Classes/004.StartupParameters.ps1 @@ -0,0 +1,150 @@ +<# + .SYNOPSIS + A class to handle startup parameters of a manged computer service object. + + .EXAMPLE + $startupParameters = [StartupParameters]::Parse(((Get-SqlDscManagedComputer).Services | ? type -eq 'SqlServer').StartupParameters) + $startupParameters | fl + $startupParameters.ToString() + + Parses the startup parameters of the database engine default instance on the + current node, and then outputs the resulting object. Also shows how the object + can be turned back to a startup parameters string by calling ToString(). + + .NOTES + This class supports an array of data file paths, log file paths, and error + log paths though currently it seems that there can only be one of each. + This class was made with arrays in case there is an unknown edge case where + it is possible to have more than one of those paths. +#> +class StartupParameters +{ + [System.String[]] + $DataFilePath + + [System.String[]] + $LogFilePath + + [System.String[]] + $ErrorLogPath + + [System.UInt32[]] + $TraceFlag + + [System.UInt32[]] + $InternalTraceFlag + + static [StartupParameters] Parse([System.String] $InstanceStartupParameters) + { + Write-Debug -Message ( + $script:localizedData.StartupParameters_DebugParsingStartupParameters -f 'StartupParameters.Parse()', $InstanceStartupParameters + ) + + $startupParameters = [StartupParameters]::new() + + $startupParameterValues = $InstanceStartupParameters -split ';' + + $startupParameters.TraceFlag = [System.UInt32[]] @( + $startupParameterValues | + Where-Object -FilterScript { + $_ -cmatch '^-T\d+' + } | + ForEach-Object -Process { + [System.UInt32] $_.TrimStart('-T') + } + ) + + Write-Debug -Message ( + $script:localizedData.StartupParameters_DebugFoundTraceFlags -f 'StartupParameters.Parse()', ($startupParameters.TraceFlag -join ', ') + ) + + $startupParameters.DataFilePath = [System.String[]] @( + $startupParameterValues | + Where-Object -FilterScript { + $_ -cmatch '^-d' + } | + ForEach-Object -Process { + $_.TrimStart('-d') + } + ) + + $startupParameters.LogFilePath = [System.String[]] @( + $startupParameterValues | + Where-Object -FilterScript { + $_ -cmatch '^-l' + } | + ForEach-Object -Process { + $_.TrimStart('-l') + } + ) + + $startupParameters.ErrorLogPath = [System.String[]] @( + $startupParameterValues | + Where-Object -FilterScript { + $_ -cmatch '^-e' + } | + ForEach-Object -Process { + $_.TrimStart('-e') + } + ) + + $startupParameters.InternalTraceFlag = [System.UInt32[]] @( + $startupParameterValues | + Where-Object -FilterScript { + $_ -cmatch '^-t\d+' + } | + ForEach-Object -Process { + [System.UInt32] $_.TrimStart('-t') + } + ) + + return $startupParameters + } + + [System.String] ToString() + { + $startupParametersValues = [System.String[]] @() + + if ($this.DataFilePath) + { + $startupParametersValues += $this.DataFilePath | + ForEach-Object -Process { + '-d{0}' -f $_ + } + } + + if ($this.ErrorLogPath) + { + $startupParametersValues += $this.ErrorLogPath | + ForEach-Object -Process { + '-e{0}' -f $_ + } + } + + if ($this.LogFilePath) + { + $startupParametersValues += $this.LogFilePath | + ForEach-Object -Process { + '-l{0}' -f $_ + } + } + + if ($this.TraceFlag) + { + $startupParametersValues += $this.TraceFlag | + ForEach-Object -Process { + '-T{0}' -f $_ + } + } + + if ($this.InternalTraceFlag) + { + $startupParametersValues += $this.InternalTraceFlag | + ForEach-Object -Process { + '-t{0}' -f $_ + } + } + + return $startupParametersValues -join ';' + } +} diff --git a/source/DSCResources/DSC_SqlServiceAccount/DSC_SqlServiceAccount.psm1 b/source/DSCResources/DSC_SqlServiceAccount/DSC_SqlServiceAccount.psm1 index b7890d0ef..febd09179 100644 --- a/source/DSCResources/DSC_SqlServiceAccount/DSC_SqlServiceAccount.psm1 +++ b/source/DSCResources/DSC_SqlServiceAccount/DSC_SqlServiceAccount.psm1 @@ -362,6 +362,11 @@ function Get-ServiceObject .EXAMPLE ConvertTo-ManagedServiceType -ServiceType 'DatabaseEngine' + + .NOTES + This helper function also exist as a private function, when this resource + is refactored into a class-based resource, this helper function can be + removed. #> function ConvertTo-ManagedServiceType { diff --git a/source/Private/Assert-ManagedServiceType.ps1 b/source/Private/Assert-ManagedServiceType.ps1 new file mode 100644 index 000000000..9c5d131c6 --- /dev/null +++ b/source/Private/Assert-ManagedServiceType.ps1 @@ -0,0 +1,63 @@ +<# + .SYNOPSIS + Assert that a computer managed service is of a certain type. + + .DESCRIPTION + Assert that a computer managed service is of a certain type. If it is the + wrong type an exception is thrown. + + .PARAMETER ServiceObject + Specifies the Service object to evaluate. + + .PARAMETER ServiceType + Specifies the normalized service type to evaluate. + + .EXAMPLE + $serviceObject = Get-SqlDscManagedComputerService -ServiceType 'DatabaseEngine' + Assert-ManagedServiceType -ServiceObject $serviceObject -ServiceType 'DatabaseEngine' + + Asserts that the computer managed service object is of the type Database Engine. + + .EXAMPLE + $serviceObject = Get-SqlDscManagedComputerService -ServiceType 'DatabaseEngine' + $serviceObject | Assert-ManagedServiceType -ServiceType 'DatabaseEngine' + + Asserts that the computer managed service object is of the type Database Engine. + + .OUTPUTS + None. +#> +function Assert-ManagedServiceType +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] + [OutputType()] + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [Microsoft.SqlServer.Management.Smo.Wmi.Service] + $ServiceObject, + + [Parameter(Mandatory = $true)] + [ValidateSet('DatabaseEngine', 'SqlServerAgent', 'Search', 'IntegrationServices', 'AnalysisServices', 'ReportingServices', 'SQLServerBrowser', 'NotificationServices')] + [System.String] + $ServiceType + ) + + process + { + $normalizedServiceType = ConvertFrom-ManagedServiceType -ServiceType $ServiceObject.Type + + if ($normalizedServiceType -ne $ServiceType) + { + $PSCmdlet.ThrowTerminatingError( + [System.Management.Automation.ErrorRecord]::new( + ($script:localizedData.ManagedServiceType_Assert_WrongServiceType -f $ServiceType, $normalizedServiceType), + 'AMST0001', # cSpell: disable-line + [System.Management.Automation.ErrorCategory]::InvalidOperation, + $ServiceObject + ) + ) + } + } +} diff --git a/source/Private/ConvertFrom-ManagedServiceType.ps1 b/source/Private/ConvertFrom-ManagedServiceType.ps1 new file mode 100644 index 000000000..2da1f68c9 --- /dev/null +++ b/source/Private/ConvertFrom-ManagedServiceType.ps1 @@ -0,0 +1,111 @@ +<# + .SYNOPSIS + Converts a managed service type name to a normalized service type name. + + .DESCRIPTION + Converts a managed service type name to its normalized service type name + equivalent. + + .PARAMETER ServiceType + Specifies the managed service type to convert to the correct normalized + service type name. + + .EXAMPLE + ConvertFrom-ManagedServiceType -ServiceType 'SqlServer' + + Returns the normalized service type name 'DatabaseEngine' . +#> +function ConvertFrom-ManagedServiceType +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [Microsoft.SqlServer.Management.Smo.Wmi.ManagedServiceType] + $ServiceType + ) + + process + { + # Map the normalized service type to a valid value from the managed service type. + switch ($ServiceType) + { + 'SqlServer' + { + $serviceTypeValue = 'DatabaseEngine' + + break + } + + 'SqlAgent' + { + $serviceTypeValue = 'SqlServerAgent' + + break + } + + 'Search' + { + $serviceTypeValue = 'Search' + + break + } + + 'SqlServerIntegrationService' + { + $serviceTypeValue = 'IntegrationServices' + + break + } + + 'AnalysisServer' + { + $serviceTypeValue = 'AnalysisServices' + + break + } + + 'ReportServer' + { + $serviceTypeValue = 'ReportingServices' + + break + } + + 'SqlBrowser' + { + $serviceTypeValue = 'SQLServerBrowser' + + break + } + + 'NotificationServer' + { + $serviceTypeValue = 'NotificationServices' + + break + } + + default + { + <# + This catches any future values in the enum ManagedServiceType + that are not yet supported. + #> + $writeErrorParameters = @{ + Message = $script:localizedData.ManagedServiceType_ConvertFrom_UnknownServiceType -f $ServiceType + Category = 'InvalidOperation' + ErrorId = 'CFMST0001' # CSpell: disable-line + TargetObject = $ServiceType + } + + Write-Error @writeErrorParameters + + break + } + } + + return $serviceTypeValue + } +} diff --git a/source/Private/ConvertTo-ManagedServiceType.ps1 b/source/Private/ConvertTo-ManagedServiceType.ps1 new file mode 100644 index 000000000..dd98f5102 --- /dev/null +++ b/source/Private/ConvertTo-ManagedServiceType.ps1 @@ -0,0 +1,93 @@ +<# + .SYNOPSIS + Converts a normalized service type name to a managed service type name. + + .DESCRIPTION + Converts a normalized service type name to its managed service type name + equivalent. + + .PARAMETER ServiceType + Specifies the normalized service type to convert to the correct manged + service type. + + .EXAMPLE + ConvertTo-ManagedServiceType -ServiceType 'DatabaseEngine' + + Returns the manged service type name for the normalized service type 'DatabaseEngine'. +#> +function ConvertTo-ManagedServiceType +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [ValidateSet('DatabaseEngine', 'SqlServerAgent', 'Search', 'IntegrationServices', 'AnalysisServices', 'ReportingServices', 'SQLServerBrowser', 'NotificationServices')] + [System.String] + $ServiceType + ) + + process + { + # Map the normalized service type to a valid value from the managed service type. + switch ($ServiceType) + { + 'DatabaseEngine' + { + $serviceTypeValue = 'SqlServer' + + break + } + + 'SqlServerAgent' + { + $serviceTypeValue = 'SqlAgent' + + break + } + + 'Search' + { + $serviceTypeValue = 'Search' + + break + } + + 'IntegrationServices' + { + $serviceTypeValue = 'SqlServerIntegrationService' + + break + } + + 'AnalysisServices' + { + $serviceTypeValue = 'AnalysisServer' + + break + } + + 'ReportingServices' + { + $serviceTypeValue = 'ReportServer' + + break + } + + 'SQLServerBrowser' + { + $serviceTypeValue = 'SqlBrowser' + + break + } + + 'NotificationServices' + { + $serviceTypeValue = 'NotificationServer' + + break + } + } + + return $serviceTypeValue -as [Microsoft.SqlServer.Management.Smo.Wmi.ManagedServiceType] + } +} diff --git a/source/Public/Add-SqlDscTraceFlag.ps1 b/source/Public/Add-SqlDscTraceFlag.ps1 new file mode 100644 index 000000000..ab6e096da --- /dev/null +++ b/source/Public/Add-SqlDscTraceFlag.ps1 @@ -0,0 +1,136 @@ +<# + .SYNOPSIS + Add trace flags to a Database Engine instance. + + .DESCRIPTION + Add trace flags on a Database Engine instance, keeping any trace flags + currently set. + + .PARAMETER ServiceObject + Specifies the Service object on which to add the trace flags. + + .PARAMETER ServerName + Specifies the server name where the instance exist. + + .PARAMETER InstanceName + Specifies the instance name on which to remove the trace flags. + + .PARAMETER TraceFlag + Specifies the trace flags to add. + + .PARAMETER Force + Specifies that the trace flag should be added with out any confirmation. + + .EXAMPLE + Add-SqlDscTraceFlag -TraceFlag 4199 + + Adds the trace flag 4199 on the Database Engine default instance + on the server where the command in run. + + .EXAMPLE + $serviceObject = Get-SqlDscManagedComputerService -ServiceType 'DatabaseEngine' + Add-SqlDscTraceFlag -ServiceObject $serviceObject -TraceFlag 4199 + + Adds the trace flag 4199 on the Database Engine default instance + on the server where the command in run. + + .EXAMPLE + Add-SqlDscTraceFlag -InstanceName 'SQL2022' -TraceFlag 4199,3226 + + Adds the trace flags 4199 and 3226 on the Database Engine instance + 'SQL2022' on the server where the command in run. + + .EXAMPLE + $serviceObject = Get-SqlDscManagedComputerService -ServiceType 'DatabaseEngine' -InstanceName 'SQL2022' + Add-SqlDscTraceFlag -ServiceObject $serviceObject -TraceFlag 4199,3226 + + Adds the trace flags 4199 and 3226 on the Database Engine instance + 'SQL2022' on the server where the command in run. + + .OUTPUTS + None. +#> +function Add-SqlDscTraceFlag +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] + [OutputType()] + [CmdletBinding(DefaultParameterSetName = 'ByServerName', SupportsShouldProcess = $true, ConfirmImpact = 'High')] + param + ( + [Parameter(ParameterSetName = 'ByServiceObject', Mandatory = $true, ValueFromPipeline = $true)] + [Microsoft.SqlServer.Management.Smo.Wmi.Service] + $ServiceObject, + + [Parameter(ParameterSetName = 'ByServerName')] + [ValidateNotNullOrEmpty()] + [System.String] + $ServerName = (Get-ComputerName), + + [Parameter(ParameterSetName = 'ByServerName')] + [ValidateNotNullOrEmpty()] + [System.String] + $InstanceName = 'MSSQLSERVER', + + [Parameter(Mandatory = $true)] + [System.UInt32[]] + $TraceFlag, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Force + ) + + begin + { + if ($Force.IsPresent) + { + $ConfirmPreference = 'None' + } + } + + process + { + if ($PSCmdlet.ParameterSetName -eq 'ByServiceObject') + { + $InstanceName = $ServiceObject.Name -replace '^MSSQL\$' + } + + # Copy $PSBoundParameters to keep it intact. + $getSqlDscTraceFlagParameters = @{} + $PSBoundParameters + + $commonParameters = [System.Management.Automation.PSCmdlet]::OptionalCommonParameters + + # Remove parameters that Get-SqlDscTraceFLag does not have/support. + $commonParameters + @('Force', 'TraceFlag') | + ForEach-Object -Process { + $getSqlDscTraceFlagParameters.Remove($_) + } + + $currentTraceFlags = Get-SqlDscTraceFlag @getSqlDscTraceFlagParameters -ErrorAction 'Stop' + + $desiredTraceFlags = [System.UInt32[]] $currentTraceFlags + @( + $TraceFlag | + ForEach-Object -Process { + # Add only when it does not already exist. + if ($_ -notin $currentTraceFlags) + { + $_ + } + } + ) + + $verboseDescriptionMessage = $script:localizedData.TraceFlag_Add_ShouldProcessVerboseDescription -f $InstanceName, ($TraceFlag -join ', ') + $verboseWarningMessage = $script:localizedData.TraceFlag_Add_ShouldProcessVerboseWarning -f $InstanceName + $captionMessage = $script:localizedData.TraceFlag_Add_ShouldProcessCaption + + if ($PSCmdlet.ShouldProcess($verboseDescriptionMessage, $verboseWarningMessage, $captionMessage)) + { + # Copy $PSBoundParameters to keep it intact. + $setSqlDscTraceFlagParameters = @{} + $PSBoundParameters + + $setSqlDscTraceFlagParameters.TraceFLag = $desiredTraceFlags + + Set-SqlDscTraceFlag @setSqlDscTraceFlagParameters -ErrorAction 'Stop' + } + } +} diff --git a/source/Public/Get-SqlDscManagedComputer.ps1 b/source/Public/Get-SqlDscManagedComputer.ps1 new file mode 100644 index 000000000..63d1796dd --- /dev/null +++ b/source/Public/Get-SqlDscManagedComputer.ps1 @@ -0,0 +1,43 @@ +<# + .SYNOPSIS + Returns the managed computer object. + + .DESCRIPTION + Returns the managed computer object, by default for the node the command + is run on. + + .PARAMETER ServerName + Specifies the server name for which to return the managed computer object. + + .EXAMPLE + Get-SqlDscManagedComputer + + Returns the managed computer object for the current node. + + .EXAMPLE + Get-SqlDscManagedComputer -ServerName 'MyServer' + + Returns the managed computer object for the server 'MyServer'. + + .OUTPUTS + `[Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer]` +#> +function Get-SqlDscManagedComputer +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when the output type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] [OutputType([Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer])] + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $ServerName = (Get-ComputerName) + ) + + Write-Verbose -Message ( + $script:localizedData.ManagedComputer_GetState -f $ServerName + ) + + $managedComputerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer' -ArgumentList $ServerName + + return $managedComputerObject +} diff --git a/source/Public/Get-SqlDscManagedComputerService.ps1 b/source/Public/Get-SqlDscManagedComputerService.ps1 new file mode 100644 index 000000000..94c975ed0 --- /dev/null +++ b/source/Public/Get-SqlDscManagedComputerService.ps1 @@ -0,0 +1,132 @@ +<# + .SYNOPSIS + Returns one or more managed computer service objects. + + .DESCRIPTION + Returns one or more managed computer service objects, by default for the + node the command is run on. + + .PARAMETER ManagedComputerObject + Specifies the Managed Computer object to return the services from. + + .PARAMETER ServerName + Specifies the server name to return the services from. + + .PARAMETER InstanceName + Specifies the instance name to return the services for, this will exclude + any service that does not have the instance name in the service name. + + .PARAMETER ServiceType + Specifies one or more service types to return the services for. + + .EXAMPLE + Get-SqlDscManagedComputer | Get-SqlDscManagedComputerService + + Returns all the managed computer service objects for the current node. + + .EXAMPLE + Get-SqlDscManagedComputerService + + Returns all the managed computer service objects for the current node. + + .EXAMPLE + Get-SqlDscManagedComputerService -ServerName 'MyServer' + + Returns all the managed computer service objects for the server 'MyServer'. + + .EXAMPLE + Get-SqlDscManagedComputerService -ServiceType 'DatabaseEngine','AnalysisServices' + + Returns all the managed computer service objects for service types + 'DatabaseEngine' and 'AnalysisServices'. + + .EXAMPLE + Get-SqlDscManagedComputerService -InstanceName 'SQL2022' + + Returns all the managed computer service objects for instance SQL2022. + + .OUTPUTS + `[Microsoft.SqlServer.Management.Smo.Wmi.Service[]]` +#> +function Get-SqlDscManagedComputerService +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when the output type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] [OutputType([Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer])] + [OutputType([Microsoft.SqlServer.Management.Smo.Wmi.Service[]])] + [CmdletBinding(DefaultParameterSetName = 'ByServerName')] + param + ( + [Parameter(ParameterSetName = 'ByServerObject', Mandatory = $true, ValueFromPipeline = $true)] + [Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer] + $ManagedComputerObject, + + [Parameter(ParameterSetName = 'ByServerName')] + [ValidateNotNullOrEmpty()] + [System.String] + $ServerName = (Get-ComputerName), + + [Parameter()] + [System.String[]] + $InstanceName, + + [Parameter()] + [ValidateSet('DatabaseEngine', 'SQLServerAgent', 'Search', 'IntegrationServices', 'AnalysisServices', 'ReportingServices', 'SQLServerBrowser', 'NotificationServices')] + [System.String[]] + $ServiceType + ) + + begin + { + if ($PSCmdlet.ParameterSetName -eq 'ByServerName') + { + $ManagedComputerObject = Get-SqlDscManagedComputer -ServerName $ServerName + } + + Write-Verbose -Message ( + $script:localizedData.ManagedComputerService_GetState -f $ServerName + ) + + $serviceObject = $null + } + + process + { + if ($ManagedComputerObject) + { + if ($serviceObject) + { + $serviceObject += $ManagedComputerObject.Services + } + else + { + $serviceObject = $ManagedComputerObject.Services + } + } + } + + end + { + if ($serviceObject) + { + if ($PSBoundParameters.ContainsKey('ServiceType')) + { + $managedServiceType = $ServiceType | + ConvertTo-ManagedServiceType + + $serviceObject = $serviceObject | + Where-Object -FilterScript { + $_.Type -in $managedServiceType + } + } + + if ($PSBoundParameters.ContainsKey('InstanceName')) + { + $serviceObject = $serviceObject | + Where-Object -FilterScript { + $_.Name -match ('\${0}$' -f $InstanceName) + } + } + } + + return $serviceObject + } +} diff --git a/source/Public/Get-SqlDscStartupParameter.ps1 b/source/Public/Get-SqlDscStartupParameter.ps1 new file mode 100644 index 000000000..e03716f9a --- /dev/null +++ b/source/Public/Get-SqlDscStartupParameter.ps1 @@ -0,0 +1,114 @@ +<# + .SYNOPSIS + Get current startup parameters on a Database Engine instance. + + .DESCRIPTION + Get current startup parameters on a Database Engine instance. + + .PARAMETER ServiceObject + Specifies the Service object to return the trace flags from. + + .PARAMETER ServerName + Specifies the server name to return the trace flags from. + + .PARAMETER InstanceName + Specifies the instance name to return the trace flags for. + + .EXAMPLE + Get-SqlDscStartupParameter + + Get the startup parameters from the Database Engine default instance on + the server where the command in run. + + .EXAMPLE + $serviceObject = Get-SqlDscManagedComputerService -ServiceType 'DatabaseEngine' + Get-SqlDscStartupParameter -ServiceObject $serviceObject + + Get the startup parameters from the Database Engine default instance on + the server where the command in run. + + .EXAMPLE + Get-SqlDscStartupParameter -InstanceName 'SQL2022' + + Get the startup parameters from the Database Engine instance 'SQL2022' on + the server where the command in run. + + .EXAMPLE + $serviceObject = Get-SqlDscManagedComputerService -ServiceType 'DatabaseEngine' -InstanceName 'SQL2022' + Get-SqlDscStartupParameter -ServiceObject $serviceObject + + Get the startup parameters from the Database Engine instance 'SQL2022' on + the server where the command in run. + + .OUTPUTS + `[StartupParameters]` +#> +function Get-SqlDscStartupParameter +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] + [OutputType([StartupParameters])] + [CmdletBinding(DefaultParameterSetName = 'ByServerName')] + param + ( + [Parameter(ParameterSetName = 'ByServiceObject', Mandatory = $true)] + [Microsoft.SqlServer.Management.Smo.Wmi.Service] + $ServiceObject, + + [Parameter(ParameterSetName = 'ByServerName')] + [ValidateNotNullOrEmpty()] + [System.String] + $ServerName = (Get-ComputerName), + + [Parameter(ParameterSetName = 'ByServerName')] + [ValidateNotNullOrEmpty()] + [System.String] + $InstanceName = 'MSSQLSERVER' + ) + + Assert-ElevatedUser -ErrorAction 'Stop' + + if ($PSCmdlet.ParameterSetName -eq 'ByServiceObject') + { + $ServiceObject | Assert-ManagedServiceType -ServiceType 'DatabaseEngine' + } + + if ($PSCmdlet.ParameterSetName -eq 'ByServerName') + { + $getSqlDscManagedComputerServiceParameters = @{ + ServerName = $ServerName + InstanceName = $InstanceName + ServiceType = 'DatabaseEngine' + } + + $ServiceObject = Get-SqlDscManagedComputerService @getSqlDscManagedComputerServiceParameters + + if (-not $ServiceObject) + { + $writeErrorParameters = @{ + Message = $script:localizedData.StartupParameter_Get_FailedToFindServiceObject + Category = 'InvalidOperation' + ErrorId = 'GSDSP0001' # CSpell: disable-line + TargetObject = $ServiceObject + } + + Write-Error @writeErrorParameters + } + } + + Write-Verbose -Message ( + $script:localizedData.StartupParameter_Get_ReturnStartupParameters -f $InstanceName, $ServerName + ) + + $startupParameters = $null + + if ($ServiceObject.StartupParameters) + { + $startupParameters = [StartupParameters]::Parse($ServiceObject.StartupParameters) + } + else + { + Write-Debug -Message ($script:localizedData.StartupParameter_Get_FailedToFindStartupParameters -f $MyInvocation.MyCommand) + } + + return $startupParameters +} diff --git a/source/Public/Get-SqlDscTraceFlag.ps1 b/source/Public/Get-SqlDscTraceFlag.ps1 new file mode 100644 index 000000000..594ebb72d --- /dev/null +++ b/source/Public/Get-SqlDscTraceFlag.ps1 @@ -0,0 +1,87 @@ +<# + .SYNOPSIS + Get current trace flags on a Database Engine instance. + + .DESCRIPTION + Get current trace flags on a Database Engine instance. + + .PARAMETER ServiceObject + Specifies the Service object to return the trace flags from. + + .PARAMETER ServerName + Specifies the server name to return the trace flags from. + + .PARAMETER InstanceName + Specifies the instance name to return the trace flags for. + + .EXAMPLE + Get-SqlDscTraceFlag + + Get all the trace flags from the Database Engine default instance on the + server where the command in run. + + .EXAMPLE + $serviceObject = Get-SqlDscManagedComputerService -ServiceType 'DatabaseEngine' + Get-SqlDscTraceFlag -ServiceObject $serviceObject + + Get all the trace flags from the Database Engine default instance on the + server where the command in run. + + .EXAMPLE + Get-SqlDscTraceFlag -InstanceName 'SQL2022' + + Get all the trace flags from the Database Engine instance 'SQL2022' on the + server where the command in run. + + .EXAMPLE + $serviceObject = Get-SqlDscManagedComputerService -ServiceType 'DatabaseEngine' -InstanceName 'SQL2022' + Get-SqlDscTraceFlag -ServiceObject $serviceObject + + Get all the trace flags from the Database Engine instance 'SQL2022' on the + server where the command in run. + + .OUTPUTS + `[System.UInt32[]]` +#> +function Get-SqlDscTraceFlag +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseOutputTypeCorrectly', '', Justification = 'Because the rule does not understands that the command returns [System.UInt32[]] when using , (comma) in the return statement')] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] + [OutputType([System.UInt32[]])] + [CmdletBinding(DefaultParameterSetName = 'ByServerName')] + param + ( + [Parameter(ParameterSetName = 'ByServiceObject', Mandatory = $true)] + [Microsoft.SqlServer.Management.Smo.Wmi.Service] + $ServiceObject, + + [Parameter(ParameterSetName = 'ByServerName')] + [ValidateNotNullOrEmpty()] + [System.String] + $ServerName = (Get-ComputerName), + + [Parameter(ParameterSetName = 'ByServerName')] + [ValidateNotNullOrEmpty()] + [System.String] + $InstanceName = 'MSSQLSERVER' + ) + + Write-Verbose -Message ( + $script:localizedData.TraceFlag_Get_ReturnTraceFlags -f $InstanceName, $ServerName + ) + + $startupParameter = Get-SqlDscStartupParameter @PSBoundParameters + + $traceFlags = [System.UInt32[]] @() + + if ($startupParameter) + { + $traceFlags = $startupParameter.TraceFlag + } + + Write-Debug -Message ( + $script:localizedData.TraceFlag_Get_DebugReturningTraceFlags -f $MyInvocation.MyCommand, ($traceFlags -join ', ') + ) + + return , [System.UInt32[]] $traceFlags +} diff --git a/source/Public/Remove-SqlDscTraceFlag.ps1 b/source/Public/Remove-SqlDscTraceFlag.ps1 new file mode 100644 index 000000000..7e2f24309 --- /dev/null +++ b/source/Public/Remove-SqlDscTraceFlag.ps1 @@ -0,0 +1,144 @@ +<# + .SYNOPSIS + Removes trace flags from a Database Engine instance. + + .DESCRIPTION + Removes trace flags from a Database Engine instance, keeping any other + trace flags currently set. + + .PARAMETER ServiceObject + Specifies the Service object on which to remove the trace flags. + + .PARAMETER ServerName + Specifies the server name where the instance exist. + + .PARAMETER InstanceName + Specifies the instance name on which to remove the trace flags. + + .PARAMETER TraceFlag + Specifies the trace flags to remove. + + .PARAMETER Force + Specifies that the trace flag should be removed with out any confirmation. + + .EXAMPLE + Remove-SqlDscTraceFlag -TraceFlag 4199 + + Removes the trace flag 4199 from the Database Engine default instance + on the server where the command in run. + + .EXAMPLE + $serviceObject = Get-SqlDscManagedComputerService -ServiceType 'DatabaseEngine' + Remove-SqlDscTraceFlag -ServiceObject $serviceObject -TraceFlag 4199 + + Removes the trace flag 4199 from the Database Engine default instance + on the server where the command in run. + + .EXAMPLE + Remove-SqlDscTraceFlag -InstanceName 'SQL2022' -TraceFlag 4199,3226 + + Removes the trace flags 4199 and 3226 from the Database Engine instance + 'SQL2022' on the server where the command in run. + + .EXAMPLE + $serviceObject = Get-SqlDscManagedComputerService -ServiceType 'DatabaseEngine' -InstanceName 'SQL2022' + Remove-SqlDscTraceFlag -ServiceObject $serviceObject -TraceFlag 4199,3226 + + Removes the trace flags 4199 and 3226 from the Database Engine instance + 'SQL2022' on the server where the command in run. + + .OUTPUTS + None. +#> +function Remove-SqlDscTraceFlag +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] + [OutputType()] + [CmdletBinding(DefaultParameterSetName = 'ByServerName', SupportsShouldProcess = $true, ConfirmImpact = 'High')] + param + ( + [Parameter(ParameterSetName = 'ByServiceObject', Mandatory = $true, ValueFromPipeline = $true)] + [Microsoft.SqlServer.Management.Smo.Wmi.Service] + $ServiceObject, + + [Parameter(ParameterSetName = 'ByServerName')] + [ValidateNotNullOrEmpty()] + [System.String] + $ServerName = (Get-ComputerName), + + [Parameter(ParameterSetName = 'ByServerName')] + [ValidateNotNullOrEmpty()] + [System.String] + $InstanceName = 'MSSQLSERVER', + + [Parameter(Mandatory = $true)] + [System.UInt32[]] + $TraceFlag, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Force + ) + + begin + { + if ($Force.IsPresent) + { + $ConfirmPreference = 'None' + } + } + + process + { + if ($PSCmdlet.ParameterSetName -eq 'ByServiceObject') + { + $InstanceName = $ServiceObject.Name -replace '^MSSQL\$' + } + + # Copy $PSBoundParameters to keep it intact. + $getSqlDscTraceFlagParameters = @{} + $PSBoundParameters + + $commonParameters = [System.Management.Automation.PSCmdlet]::OptionalCommonParameters + + # Remove parameters that Get-SqlDscTraceFLag does not have/support. + $commonParameters + @('Force', 'TraceFlag') | + ForEach-Object -Process { + $getSqlDscTraceFlagParameters.Remove($_) + } + + $currentTraceFlags = Get-SqlDscTraceFlag @getSqlDscTraceFlagParameters -ErrorAction 'Stop' + + if ($currentTraceFlags) + { + # Must always return an array. An empty array when removing the last value. + $desiredTraceFlags = [System.UInt32[]] @( + $currentTraceFlags | + ForEach-Object -Process { + # Keep values that should not be removed. + if ($_ -notin $TraceFlag) + { + $_ + } + } + ) + + $verboseDescriptionMessage = $script:localizedData.TraceFlag_Remove_ShouldProcessVerboseDescription -f $InstanceName, ($TraceFlag -join ', ') + $verboseWarningMessage = $script:localizedData.TraceFlag_Remove_ShouldProcessVerboseWarning -f $InstanceName + $captionMessage = $script:localizedData.TraceFlag_Remove_ShouldProcessCaption + + if ($PSCmdlet.ShouldProcess($verboseDescriptionMessage, $verboseWarningMessage, $captionMessage)) + { + # Copy $PSBoundParameters to keep it intact. + $setSqlDscTraceFlagParameters = @{} + $PSBoundParameters + + $setSqlDscTraceFlagParameters.TraceFLag = $desiredTraceFlags + + Set-SqlDscTraceFlag @setSqlDscTraceFlagParameters -ErrorAction 'Stop' + } + } + else + { + Write-Debug -Message $script:localizedData.TraceFlag_Remove_NoCurrentTraceFlags + } + } +} diff --git a/source/Public/Set-SqlDscStartupParameter.ps1 b/source/Public/Set-SqlDscStartupParameter.ps1 new file mode 100644 index 000000000..38e2f94f4 --- /dev/null +++ b/source/Public/Set-SqlDscStartupParameter.ps1 @@ -0,0 +1,160 @@ +<# + .SYNOPSIS + Sets startup parameters on a Database Engine instance. + + .DESCRIPTION + Sets startup parameters on a Database Engine instance. + + .PARAMETER ServiceObject + Specifies the Service object on which to set the startup parameters. + + .PARAMETER ServerName + Specifies the server name where the instance exist. + + .PARAMETER InstanceName + Specifies the instance name on which to set the startup parameters. + + .PARAMETER TraceFlag + Specifies the trace flags to set. + + .PARAMETER InternalTraceFlag + Specifies the internal trace flags to set. + + From the [Database Engine Service Startup Options](https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/database-engine-service-startup-options) + documentation: "...this sets other internal trace flags that are required + only by SQL Server support engineers." + + .PARAMETER Force + Specifies that the startup parameters should be set with out any confirmation. + + .EXAMPLE + Set-SqlDscStartupParameters -TraceFlag 4199 + + Replaces the trace flags with 4199 on the Database Engine default instance + on the server where the command in run. + + .EXAMPLE + $serviceObject = Get-SqlDscManagedComputerService -ServiceType 'DatabaseEngine' + Set-SqlDscTraceFlag -ServiceObject $serviceObject -TraceFlag 4199 + + Replaces the trace flags with 4199 on the Database Engine default instance + on the server where the command in run. + + .EXAMPLE + Set-SqlDscTraceFlag -InstanceName 'SQL2022' -TraceFlag @() + + Removes all the trace flags from the Database Engine instance 'SQL2022' + on the server where the command in run. + + .OUTPUTS + None. + + .NOTES + This command should support setting the values according to this documentation: + https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/database-engine-service-startup-options +#> +function Set-SqlDscStartupParameter +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] + [OutputType()] + [CmdletBinding(DefaultParameterSetName = 'ByServerName', SupportsShouldProcess = $true, ConfirmImpact = 'High')] + param + ( + [Parameter(ParameterSetName = 'ByServiceObject', Mandatory = $true, ValueFromPipeline = $true)] + [Microsoft.SqlServer.Management.Smo.Wmi.Service] + $ServiceObject, + + [Parameter(ParameterSetName = 'ByServerName')] + [ValidateNotNullOrEmpty()] + [System.String] + $ServerName = (Get-ComputerName), + + [Parameter(ParameterSetName = 'ByServerName')] + [ValidateNotNullOrEmpty()] + [System.String] + $InstanceName = 'MSSQLSERVER', + + [Parameter()] + [AllowEmptyCollection()] + [System.UInt32[]] + $TraceFlag, + + [Parameter()] + [AllowEmptyCollection()] + [System.UInt32[]] + $InternalTraceFlag, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Force + ) + + begin + { + Assert-ElevatedUser -ErrorAction 'Stop' + + if ($Force.IsPresent) + { + $ConfirmPreference = 'None' + } + } + + process + { + if ($PSCmdlet.ParameterSetName -eq 'ByServiceObject') + { + $ServiceObject | Assert-ManagedServiceType -ServiceType 'DatabaseEngine' + + $InstanceName = $ServiceObject.Name -replace '^MSSQL\$' + } + + if ($PSCmdlet.ParameterSetName -eq 'ByServerName') + { + $getSqlDscManagedComputerServiceParameters = @{ + ServerName = $ServerName + InstanceName = $InstanceName + ServiceType = 'DatabaseEngine' + ErrorAction = 'Stop' + } + + $ServiceObject = Get-SqlDscManagedComputerService @getSqlDscManagedComputerServiceParameters + + if (-not $ServiceObject) + { + $writeErrorParameters = @{ + Message = $script:localizedData.StartupParameter_Set_FailedToFindServiceObject + Category = 'InvalidOperation' + ErrorId = 'SSDSP0002' # CSpell: disable-line + TargetObject = $ServiceObject + } + + Write-Error @writeErrorParameters + } + } + + if ($ServiceObject) + { + $verboseDescriptionMessage = $script:localizedData.StartupParameter_Set_ShouldProcessVerboseDescription -f $InstanceName + $verboseWarningMessage = $script:localizedData.StartupParameter_Set_ShouldProcessVerboseWarning -f $InstanceName + $captionMessage = $script:localizedData.StartupParameter_Set_ShouldProcessCaption + + if ($PSCmdlet.ShouldProcess($verboseDescriptionMessage, $verboseWarningMessage, $captionMessage)) + { + $startupParameters = [StartupParameters]::Parse($ServiceObject.StartupParameters) + + if ($PSBoundParameters.ContainsKey('TraceFlag')) + { + $startupParameters.TraceFlag = $TraceFlag + } + + if ($PSBoundParameters.ContainsKey('InternalTraceFlag')) + { + $startupParameters.InternalTraceFlag = $InternalTraceFlag + } + + $ServiceObject.StartupParameters = $startupParameters.ToString() + $ServiceObject.Alter() + } + } + } +} diff --git a/source/Public/Set-SqlDscTraceFlag.ps1 b/source/Public/Set-SqlDscTraceFlag.ps1 new file mode 100644 index 000000000..1786fe1a3 --- /dev/null +++ b/source/Public/Set-SqlDscTraceFlag.ps1 @@ -0,0 +1,114 @@ +<# + .SYNOPSIS + Sets trace flags on a Database Engine instance. + + .DESCRIPTION + Sets trace flags on a Database Engine instance, replacing any trace flags + currently set. + + .PARAMETER ServiceObject + Specifies the Service object on which to set the trace flags. + + .PARAMETER ServerName + Specifies the server name where the instance exist. + + .PARAMETER InstanceName + Specifies the instance name on which to set the trace flags. + + .PARAMETER TraceFlag + Specifies the trace flags to set. + + .PARAMETER Force + Specifies that the trace flag should be set with out any confirmation. + + .EXAMPLE + Set-SqlDscTraceFlag -TraceFlag 4199 + + Replaces the trace flags with 4199 on the Database Engine default instance + on the server where the command in run. + + .EXAMPLE + $serviceObject = Get-SqlDscManagedComputerService -ServiceType 'DatabaseEngine' + Set-SqlDscTraceFlag -ServiceObject $serviceObject -TraceFlag 4199 + + Replaces the trace flags with 4199 on the Database Engine default instance + on the server where the command in run. + + .EXAMPLE + Set-SqlDscTraceFlag -InstanceName 'SQL2022' -TraceFlag 4199,3226 + + Replaces the trace flags with 4199 and 3226 on the Database Engine instance + 'SQL2022' on the server where the command in run. + + .EXAMPLE + $serviceObject = Get-SqlDscManagedComputerService -ServiceType 'DatabaseEngine' -InstanceName 'SQL2022' + Set-SqlDscTraceFlag -ServiceObject $serviceObject -TraceFlag 4199,3226 + + Replaces the trace flags with 4199 and 3226 on the Database Engine instance + 'SQL2022' on the server where the command in run. + + .EXAMPLE + Set-SqlDscTraceFlag -InstanceName 'SQL2022' -TraceFlag @() + + Removes all the trace flags from the Database Engine instance 'SQL2022' + on the server where the command in run. + + .OUTPUTS + None. +#> +function Set-SqlDscTraceFlag +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] + [OutputType()] + [CmdletBinding(DefaultParameterSetName = 'ByServerName', SupportsShouldProcess = $true, ConfirmImpact = 'High')] + param + ( + [Parameter(ParameterSetName = 'ByServiceObject', Mandatory = $true, ValueFromPipeline = $true)] + [Microsoft.SqlServer.Management.Smo.Wmi.Service] + $ServiceObject, + + [Parameter(ParameterSetName = 'ByServerName')] + [ValidateNotNullOrEmpty()] + [System.String] + $ServerName = (Get-ComputerName), + + [Parameter(ParameterSetName = 'ByServerName')] + [ValidateNotNullOrEmpty()] + [System.String] + $InstanceName = 'MSSQLSERVER', + + [Parameter(Mandatory = $true)] + [AllowEmptyCollection()] + [System.UInt32[]] + $TraceFlag, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Force + ) + + begin + { + if ($Force.IsPresent) + { + $ConfirmPreference = 'None' + } + } + + process + { + if ($PSCmdlet.ParameterSetName -eq 'ByServiceObject') + { + $InstanceName = $ServiceObject.Name -replace '^MSSQL\$' + } + + $verboseDescriptionMessage = $script:localizedData.TraceFlag_Set_ShouldProcessVerboseDescription -f $InstanceName, ($TraceFlag -join ', ') + $verboseWarningMessage = $script:localizedData.TraceFlag_Set_ShouldProcessVerboseWarning -f $InstanceName + $captionMessage = $script:localizedData.TraceFlag_Set_ShouldProcessCaption + + if ($PSCmdlet.ShouldProcess($verboseDescriptionMessage, $verboseWarningMessage, $captionMessage)) + { + Set-SqlDscStartupParameter @PSBoundParameters + } + } +} diff --git a/source/en-US/SqlServerDsc.strings.psd1 b/source/en-US/SqlServerDsc.strings.psd1 index 34bf96c99..55ad73254 100644 --- a/source/en-US/SqlServerDsc.strings.psd1 +++ b/source/en-US/SqlServerDsc.strings.psd1 @@ -2,7 +2,8 @@ .SYNOPSIS The localized resource strings in English (en-US) for the resource SqlServerDsc module. This file should only contain - localized strings for private and public functions. + localized strings for private functions, public command, and + classes (that are not a DSC resource). #> ConvertFrom-StringData @' @@ -95,6 +96,57 @@ ConvertFrom-StringData @' InstallSqlServerProperties_ASServerModeInvalidValue = The value for ASServerMode is not valid for the setup action {0}. InstallSqlServerProperties_RsInstallModeInvalidValue = The only valid value for RsInstallMode is 'FilesOnlyMode' when using setup action {0}. + ## Get-SqlDscManagedComputer + ManagedComputer_GetState = Returning the managed computer object for server {0}. + + ## Get-SqlDscManagedComputerService + ManagedComputerService_GetState = Returning the managed computer service object(s) for server {0}. + + ## StartupParameters + StartupParameters_DebugFoundTraceFlags = {0}: Found the trace flags: {1} + StartupParameters_DebugParsingStartupParameters = {0}: Parsing the startup parameters: {1} + + ## ConvertFrom-ManagedServiceType + ManagedServiceType_ConvertFrom_UnknownServiceType = The service type '{0}' is unknown and cannot me converted to its normalized service account equivalent + + ## Assert-ManagedServiceType + ManagedServiceType_Assert_WrongServiceType = The provided ServiceObject is of the wrong type. Expected {0}, but was {1}. + + ## Get-SqlDscStartupParameter + StartupParameter_Get_ReturnStartupParameters = Returning the startup parameters for instance {0} on server {1}. + StartupParameter_Get_FailedToFindServiceObject = Failed to find the service object. + StartupParameter_Get_FailedToFindStartupParameters = {0}: Failed to find the instance's startup parameters. + + ## Set-SqlDscStartupParameter + StartupParameter_Set_ShouldProcessVerboseDescription = Setting startup parameters on the instance '{0}'. + StartupParameter_Set_ShouldProcessVerboseWarning = Are you sure you want to set the startup parameters on the instance '{0}'? + # This string shall not end with full stop (.) since it is used as a title of ShouldProcess messages. + StartupParameter_Set_ShouldProcessCaption = Set startup parameter on instance + StartupParameter_Set_FailedToFindServiceObject = Failed to find the service object. + + ## Get-SqlDscTraceFlag + TraceFlag_Get_ReturnTraceFlags = Returning the trace flags for instance {0} on server {1}. + TraceFlag_Get_DebugReturningTraceFlags = {0}: Returning the trace flag values: {1} + + ## Set-SqlDscTraceFlag + TraceFlag_Set_ShouldProcessVerboseDescription = Replacing the trace flags on the instance '{0}' with the trace flags '{1}'. + TraceFlag_Set_ShouldProcessVerboseWarning = Are you sure you want to replace the trace flags on the instance '{0}'? + # This string shall not end with full stop (.) since it is used as a title of ShouldProcess messages. + TraceFlag_Set_ShouldProcessCaption = Replace trace flag on instance + + ## Add-SqlDscTraceFlag + TraceFlag_Add_ShouldProcessVerboseDescription = Adding trace flags '{1}' to the instance '{0}'. + TraceFlag_Add_ShouldProcessVerboseWarning = Are you sure you want to add trace flags to the instance '{0}'? + # This string shall not end with full stop (.) since it is used as a title of ShouldProcess messages. + TraceFlag_Add_ShouldProcessCaption = Add trace flag on instance + + ## Remove-SqlDscTraceFlag + TraceFlag_Remove_ShouldProcessVerboseDescription = Removing trace flags '{1}' from the instance '{0}'. + TraceFlag_Remove_ShouldProcessVerboseWarning = Are you sure you want to remove the trace flags from the instance '{0}'? + # This string shall not end with full stop (.) since it is used as a title of ShouldProcess messages. + TraceFlag_Remove_ShouldProcessCaption = Remove trace flag from instance + TraceFlag_Remove_NoCurrentTraceFlags = There are no current trace flags on instance. Nothing to remove. + ## Import-SqlDscPreferredModule PreferredModule_ModuleFound = Preferred module {0} found. PreferredModule_ModuleNotFound = Information: No preferred PowerShell module was found, trying to use the SQLPS module. diff --git a/tests/Unit/Classes/StartupParameters.Tests.ps1 b/tests/Unit/Classes/StartupParameters.Tests.ps1 new file mode 100644 index 000000000..f4b8541c5 --- /dev/null +++ b/tests/Unit/Classes/StartupParameters.Tests.ps1 @@ -0,0 +1,376 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 2>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:dscModuleName + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscModuleName -All | Remove-Module -Force + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'StartupParameters' -Tag 'StartupParameters' { + Context 'When instantiating the class' { + It 'Should not throw an error' { + $script:mockStartupParametersInstance = InModuleScope -ScriptBlock { + [StartupParameters]::new() + } + } + + It 'Should be of the correct type' { + $mockStartupParametersInstance.GetType().Name | Should -Be 'StartupParameters' + } + } + + Context 'When setting and reading single values' { + It 'Should be able to set value in instance' { + $script:mockStartupParametersInstance = InModuleScope -ScriptBlock { + $startupParametersInstance = [StartupParameters]::new() + + $startupParametersInstance.DataFilePath = $TestDrive + $startupParametersInstance.LogFilePath = $TestDrive + $startupParametersInstance.ErrorLogPath = $TestDrive + $startupParametersInstance.TraceFlag = 4199 + $startupParametersInstance.InternalTraceFlag = 8688 + + return $startupParametersInstance + } + } + + It 'Should be able read the values from instance' { + $mockStartupParametersInstance | Should -Not -BeNullOrEmpty + + $mockStartupParametersInstance.DataFilePath | Should -Be $TestDrive + $mockStartupParametersInstance.LogFilePath | Should -Be $TestDrive + $mockStartupParametersInstance.ErrorLogPath | Should -Be $TestDrive + $mockStartupParametersInstance.TraceFlag | Should -Be 4199 + $mockStartupParametersInstance.InternalTraceFlag | Should -Be 8688 + } + } + + Context 'When setting and reading multiple values' { + It 'Should be able to set value in instance' { + $script:mockStartupParametersInstance = InModuleScope -ScriptBlock { + $startupParametersInstance = [StartupParameters]::new() + + $startupParametersInstance.DataFilePath = @($TestDrive, 'C:\Temp') + $startupParametersInstance.LogFilePath = @($TestDrive, 'C:\Temp') + $startupParametersInstance.ErrorLogPath = @($TestDrive, 'C:\Temp') + $startupParametersInstance.TraceFlag = @(4199, 3226) + $startupParametersInstance.InternalTraceFlag = @(8678, 8688) + + return $startupParametersInstance + } + } + + It 'Should be able read the values from instance' { + $mockStartupParametersInstance | Should -Not -BeNullOrEmpty + + $mockStartupParametersInstance.DataFilePath | Should -HaveCount 2 + $mockStartupParametersInstance.DataFilePath | Should -Contain $TestDrive + $mockStartupParametersInstance.DataFilePath | Should -Contain 'C:\Temp' + + $mockStartupParametersInstance.LogFilePath | Should -HaveCount 2 + $mockStartupParametersInstance.LogFilePath | Should -Contain $TestDrive + $mockStartupParametersInstance.LogFilePath | Should -Contain 'C:\Temp' + + $mockStartupParametersInstance.ErrorLogPath | Should -HaveCount 2 + $mockStartupParametersInstance.ErrorLogPath | Should -Contain $TestDrive + $mockStartupParametersInstance.ErrorLogPath | Should -Contain 'C:\Temp' + + $mockStartupParametersInstance.TraceFlag | Should -HaveCount 2 + $mockStartupParametersInstance.TraceFlag | Should -Contain 4199 + $mockStartupParametersInstance.TraceFlag | Should -Contain 3226 + + $mockStartupParametersInstance.InternalTraceFlag | Should -HaveCount 2 + $mockStartupParametersInstance.InternalTraceFlag | Should -Contain 8678 + $mockStartupParametersInstance.InternalTraceFlag | Should -Contain 8688 + } + } + + Context 'When parsing startup parameters' { + Context 'When there are only default startup parameters' { + It 'Should parse the values correctly' { + $script:mockStartupParametersInstance = InModuleScope -ScriptBlock { + $startupParametersInstance = [StartupParameters]::Parse('-dC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf;-eC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG;-lC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf') + + return $startupParametersInstance + } + + $mockStartupParametersInstance | Should -Not -BeNullOrEmpty + } + + It 'Should have the correct value for ' -ForEach @( + @{ + MockPropertyName = 'DataFilePath' + MockExpectedValue = 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf' + } + @{ + MockPropertyName = 'LogFilePath' + MockExpectedValue = 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf' + } + @{ + MockPropertyName = 'ErrorLogPath' + MockExpectedValue = 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG' + } + ) { + $mockStartupParametersInstance.$MockPropertyName | Should -Be $MockExpectedValue + } + + It 'Should have the correct value for TraceFlag' { + $mockStartupParametersInstance.TraceFlag | Should -BeNullOrEmpty + $mockStartupParametersInstance.TraceFlag | Should -HaveCount 0 + } + + It 'Should have the correct value for InternalTraceFlag' { + $mockStartupParametersInstance.InternalTraceFlag | Should -BeNullOrEmpty + $mockStartupParametersInstance.InternalTraceFlag | Should -HaveCount 0 + } + } + + Context 'When there are a single trace flag' { + It 'Should parse the values correctly' { + $script:mockStartupParametersInstance = InModuleScope -ScriptBlock { + $startupParametersInstance = [StartupParameters]::Parse('-dC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf;-eC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG;-lC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf;-T4199') + + return $startupParametersInstance + } + + $mockStartupParametersInstance | Should -Not -BeNullOrEmpty + } + + It 'Should have the correct value for ' -ForEach @( + @{ + MockPropertyName = 'DataFilePath' + MockExpectedValue = 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf' + } + @{ + MockPropertyName = 'LogFilePath' + MockExpectedValue = 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf' + } + @{ + MockPropertyName = 'ErrorLogPath' + MockExpectedValue = 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG' + } + ) { + $mockStartupParametersInstance.$MockPropertyName | Should -Be $MockExpectedValue + } + + It 'Should have the correct value for TraceFlag' { + $mockStartupParametersInstance.TraceFlag | Should -HaveCount 1 + $mockStartupParametersInstance.TraceFlag | Should -Be 4199 + } + } + + Context 'When there are multiple trace flags' { + It 'Should parse the values correctly' { + $script:mockStartupParametersInstance = InModuleScope -ScriptBlock { + $startupParametersInstance = [StartupParameters]::Parse('-dC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf;-eC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG;-lC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf;-T4199;-T3226') + + return $startupParametersInstance + } + + $mockStartupParametersInstance | Should -Not -BeNullOrEmpty + } + + It 'Should have the correct value for ' -ForEach @( + @{ + MockPropertyName = 'DataFilePath' + MockExpectedValue = 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf' + } + @{ + MockPropertyName = 'LogFilePath' + MockExpectedValue = 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf' + } + @{ + MockPropertyName = 'ErrorLogPath' + MockExpectedValue = 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG' + } + ) { + $mockStartupParametersInstance.$MockPropertyName | Should -Be $MockExpectedValue + } + + It 'Should have the correct value for TraceFlag' { + $mockStartupParametersInstance.TraceFlag | Should -HaveCount 2 + $mockStartupParametersInstance.TraceFlag | Should -Contain 4199 + $mockStartupParametersInstance.TraceFlag | Should -Contain 3226 + } + } + + Context 'When there are a single internal trace flag' { + It 'Should parse the values correctly' { + $script:mockStartupParametersInstance = InModuleScope -ScriptBlock { + $startupParametersInstance = [StartupParameters]::Parse('-dC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf;-eC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG;-lC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf;-t8688') + + return $startupParametersInstance + } + + $mockStartupParametersInstance | Should -Not -BeNullOrEmpty + } + + # Evaluates that startup parameter '-t' is not also interpreted as '-T'. + It 'Should have the correct value for TraceFlag' { + $mockStartupParametersInstance.TraceFlag | Should -HaveCount 0 + } + + It 'Should have the correct value for InternalTraceFlag' { + $mockStartupParametersInstance.InternalTraceFlag | Should -HaveCount 1 + $mockStartupParametersInstance.InternalTraceFlag | Should -Be 8688 + } + } + + Context 'When there are multiple internal trace flags' { + It 'Should parse the values correctly' { + $script:mockStartupParametersInstance = InModuleScope -ScriptBlock { + $startupParametersInstance = [StartupParameters]::Parse('-dC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf;-eC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG;-lC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf;-t8688;-t8678') + + return $startupParametersInstance + } + + $mockStartupParametersInstance | Should -Not -BeNullOrEmpty + } + + It 'Should have the correct value for InternalTraceFlag' { + $mockStartupParametersInstance.InternalTraceFlag | Should -HaveCount 2 + $mockStartupParametersInstance.InternalTraceFlag | Should -Contain 8688 + $mockStartupParametersInstance.InternalTraceFlag | Should -Contain 8678 + } + } + } + + Context 'When converting startup parameters to string representation' { + BeforeAll { + $mockDefaultExpectedValue = '-d{0};-e{0};-l{0}' -f $TestDrive + } + + Context 'When there are no trace flags' { + It 'Should output the values correctly' { + $script:mockStartupParametersInstance = InModuleScope -ScriptBlock { + $startupParametersInstance = [StartupParameters]::new() + + $startupParametersInstance.DataFilePath = $TestDrive + $startupParametersInstance.LogFilePath = $TestDrive + $startupParametersInstance.ErrorLogPath = $TestDrive + + return $startupParametersInstance + } + + $mockStartupParametersInstance.ToString() | Should -Be $mockDefaultExpectedValue + } + } + + Context 'When there are a single trace flag' { + It 'Should output the values correctly' { + $script:mockStartupParametersInstance = InModuleScope -ScriptBlock { + $startupParametersInstance = [StartupParameters]::new() + + $startupParametersInstance.DataFilePath = $TestDrive + $startupParametersInstance.LogFilePath = $TestDrive + $startupParametersInstance.ErrorLogPath = $TestDrive + $startupParametersInstance.TraceFlag = 4199 + + return $startupParametersInstance + } + + $mockStartupParametersInstance.ToString() | Should -Be ($mockDefaultExpectedValue + ';-T4199') + } + } + + Context 'When there are a single trace flag' { + It 'Should output the values correctly' { + $script:mockStartupParametersInstance = InModuleScope -ScriptBlock { + $startupParametersInstance = [StartupParameters]::new() + + $startupParametersInstance.DataFilePath = $TestDrive + $startupParametersInstance.LogFilePath = $TestDrive + $startupParametersInstance.ErrorLogPath = $TestDrive + $startupParametersInstance.TraceFlag = @(4199, 3226) + + return $startupParametersInstance + } + + $mockStartupParametersInstance.ToString() | Should -BeLike ($mockDefaultExpectedValue + '*') + $mockStartupParametersInstance.ToString() | Should -MatchExactly ';-T4199' + $mockStartupParametersInstance.ToString() | Should -MatchExactly ';-T3226' + } + } + + Context 'When there are a single internal trace flag' { + It 'Should output the values correctly' { + $script:mockStartupParametersInstance = InModuleScope -ScriptBlock { + $startupParametersInstance = [StartupParameters]::new() + + $startupParametersInstance.DataFilePath = $TestDrive + $startupParametersInstance.LogFilePath = $TestDrive + $startupParametersInstance.ErrorLogPath = $TestDrive + $startupParametersInstance.InternalTraceFlag = 8688 + + return $startupParametersInstance + } + + $mockStartupParametersInstance.ToString() | Should -Be ($mockDefaultExpectedValue + ';-t8688') + } + } + + Context 'When there are multiple internal trace flags' { + It 'Should output the values correctly' { + $script:mockStartupParametersInstance = InModuleScope -ScriptBlock { + $startupParametersInstance = [StartupParameters]::new() + + $startupParametersInstance.DataFilePath = $TestDrive + $startupParametersInstance.LogFilePath = $TestDrive + $startupParametersInstance.ErrorLogPath = $TestDrive + $startupParametersInstance.InternalTraceFlag = @(8688, 8678) + + return $startupParametersInstance + } + + $mockStartupParametersInstance.ToString() | Should -BeLike ($mockDefaultExpectedValue + '*') + $mockStartupParametersInstance.ToString() | Should -MatchExactly ';-t8688' + $mockStartupParametersInstance.ToString() | Should -MatchExactly ';-t8678' + } + + It 'Should not have set any ''-T'' parameters' { + $mockStartupParametersInstance.ToString() | Should -Not -MatchExactly ';-T8688' + $mockStartupParametersInstance.ToString() | Should -Not -MatchExactly ';-T8678' + } + } + } +} diff --git a/tests/Unit/Private/Assert-ManagedServiceType.Tests.ps1 b/tests/Unit/Private/Assert-ManagedServiceType.Tests.ps1 new file mode 100644 index 000000000..173da158d --- /dev/null +++ b/tests/Unit/Private/Assert-ManagedServiceType.Tests.ps1 @@ -0,0 +1,122 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', Justification = 'because ConvertTo-SecureString is used to simplify the tests.')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 2>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:dscModuleName + + # Loading mocked classes + Add-Type -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath '../Stubs') -ChildPath 'SMO.cs') + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscModuleName -All | Remove-Module -Force + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'Assert-ManagedServiceType' -Tag 'Private' { + Context 'When types match' { + BeforeAll { + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.Type = 'SqlServer' + + Mock -CommandName ConvertFrom-ManagedServiceType -MockWith { + return 'DatabaseEngine' + } + } + + It 'Should not throw an exception' { + $_.MockServiceObject = $mockServiceObject + + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + { + $MockServiceObject | + Assert-ManagedServiceType -ServiceType 'DatabaseEngine' -ErrorAction 'Stop' + } | Should -Not -Throw + } + } + } + + Context 'When the types mismatch' { + BeforeAll { + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.Type = 'SqlServer' + + Mock -CommandName ConvertFrom-ManagedServiceType -MockWith { + return 'DatabaseEngine' + } + } + + Context 'When passing Stop for parameter ErrorAction' { + It 'Should throw the correct error' { + $_.MockServiceObject = $mockServiceObject + + InModuleScope -Parameter $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + $mockErrorMessage = $script:localizedData.ManagedServiceType_Assert_WrongServiceType -f 'SqlServerAgent', 'DatabaseEngine' + + { + $MockServiceObject | + Assert-ManagedServiceType -ServiceType 'SqlServerAgent' -ErrorAction 'Stop' + } | Should -Throw -ExpectedMessage $mockErrorMessage + } + } + } + + Context 'When passing SilentlyContinue for parameter ErrorAction' { + It 'Should still throw a termination error' { + $_.MockServiceObject = $mockServiceObject + + InModuleScope -Parameter $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + $mockErrorMessage = $script:localizedData.ManagedServiceType_Assert_WrongServiceType -f 'SqlServerAgent', 'DatabaseEngine' + + { + $MockServiceObject | + Assert-ManagedServiceType -ServiceType 'SqlServerAgent' -ErrorAction 'SilentlyContinue' + } | Should -Throw -ExpectedMessage $mockErrorMessage + } + } + } + } +} diff --git a/tests/Unit/Private/ConvertFrom-ManagedServiceType.Tests.ps1 b/tests/Unit/Private/ConvertFrom-ManagedServiceType.Tests.ps1 new file mode 100644 index 000000000..ca0dcda78 --- /dev/null +++ b/tests/Unit/Private/ConvertFrom-ManagedServiceType.Tests.ps1 @@ -0,0 +1,123 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', Justification = 'because ConvertTo-SecureString is used to simplify the tests.')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 2>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:dscModuleName + + # Loading mocked classes + Add-Type -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath '../Stubs') -ChildPath 'SMO.cs') + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscModuleName -All | Remove-Module -Force + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'ConvertFrom-ManagedServiceType' -Tag 'Private' { + Context 'When translating to a normalized service types' { + BeforeDiscovery { + $testCases = @( + @{ + MockServiceType = 'SqlServer' + MockExpectedType = 'DatabaseEngine' + } + + @{ + MockServiceType = 'SqlAgent' + MockExpectedType = 'SqlServerAgent' + } + + @{ + MockServiceType = 'Search' + MockExpectedType = 'Search' + } + + @{ + MockServiceType = 'SqlServerIntegrationService' + MockExpectedType = 'IntegrationServices' + } + + @{ + MockServiceType = 'AnalysisServer' + MockExpectedType = 'AnalysisServices' + } + + @{ + MockServiceType = 'ReportServer' + MockExpectedType = 'ReportingServices' + } + + @{ + MockServiceType = 'SqlBrowser' + MockExpectedType = 'SQLServerBrowser' + } + + @{ + MockServiceType = 'NotificationServer' + MockExpectedType = 'NotificationServices' + } + ) + } + + It 'Should properly map '''' to normalized service type ''''' -ForEach $testCases { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + # Get the ManagedServiceType + $managedServiceType = ConvertFrom-ManagedServiceType -ServiceType $MockServiceType + + $managedServiceType | Should -BeOfType [System.String] + $managedServiceType | Should -Be $MockExpectedType + } + } + } + + Context 'When converting a type that is not supported' { + It 'Should throw the correct error' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $mockErrorMessage = '*Unable to match the identifier name UnknownType to a valid enumerator name*' + + { ConvertFrom-ManagedServiceType -ServiceType 'UnknownType' -ErrorAction 'Stop' } | Should -Throw -ExpectedMessage $mockErrorMessage + } + } + } +} diff --git a/tests/Unit/Private/ConvertTo-ManagedServiceType.Tests.ps1 b/tests/Unit/Private/ConvertTo-ManagedServiceType.Tests.ps1 new file mode 100644 index 000000000..626d35386 --- /dev/null +++ b/tests/Unit/Private/ConvertTo-ManagedServiceType.Tests.ps1 @@ -0,0 +1,123 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', Justification = 'because ConvertTo-SecureString is used to simplify the tests.')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 2>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:dscModuleName + + # Loading mocked classes + Add-Type -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath '../Stubs') -ChildPath 'SMO.cs') + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscModuleName -All | Remove-Module -Force + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'ConvertTo-ManagedServiceType' -Tag 'Private' { + Context 'When translating to managed service types' { + BeforeDiscovery { + $testCases = @( + @{ + MockServiceType = 'DatabaseEngine' + MockExpectedType = 'SqlServer' + } + + @{ + MockServiceType = 'SqlServerAgent' + MockExpectedType = 'SqlAgent' + } + + @{ + MockServiceType = 'Search' + MockExpectedType = 'Search' + } + + @{ + MockServiceType = 'IntegrationServices' + MockExpectedType = 'SqlServerIntegrationService' + } + + @{ + MockServiceType = 'AnalysisServices' + MockExpectedType = 'AnalysisServer' + } + + @{ + MockServiceType = 'ReportingServices' + MockExpectedType = 'ReportServer' + } + + @{ + MockServiceType = 'SQLServerBrowser' + MockExpectedType = 'SqlBrowser' + } + + @{ + MockServiceType = 'NotificationServices' + MockExpectedType = 'NotificationServer' + } + ) + } + + It 'Should properly map '''' to managed service type ''''' -ForEach $testCases { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + # Get the ManagedServiceType + $managedServiceType = ConvertTo-ManagedServiceType -ServiceType $MockServiceType + + $managedServiceType | Should -BeOfType 'Microsoft.SqlServer.Management.Smo.Wmi.ManagedServiceType' + $managedServiceType | Should -Be $MockExpectedType + } + } + } + + Context 'When converting a type that is not supported' { + It 'Should throw the correct error' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $mockErrorMessage = 'Cannot validate argument on parameter ''ServiceType''. The argument "UnknownType" does not belong to the set "DatabaseEngine,SQLServerAgent,Search,IntegrationServices,AnalysisServices,ReportingServices,SQLServerBrowser,NotificationServices" specified by the ValidateSet attribute. Supply an argument that is in the set and then try the command again.' + + { ConvertTo-ManagedServiceType -ServiceType 'UnknownType' -ErrorAction 'Stop' } | Should -Throw -ExpectedMessage $mockErrorMessage + } + } + } +} diff --git a/tests/Unit/Private/Invoke-SetupAction.Tests.ps1 b/tests/Unit/Private/Invoke-SetupAction.Tests.ps1 index 2d36af82b..44a04161d 100644 --- a/tests/Unit/Private/Invoke-SetupAction.Tests.ps1 +++ b/tests/Unit/Private/Invoke-SetupAction.Tests.ps1 @@ -47,7 +47,7 @@ AfterAll { Remove-Item -Path 'env:SqlServerDscCI' } -Describe 'Invoke-SetupAction' -Tag 'Public' { +Describe 'Invoke-SetupAction' -Tag 'Private' { It 'Should have the correct parameters in parameter set ' -ForEach @( @{ MockParameterSetName = 'Install' diff --git a/tests/Unit/Public/Add-SqlDscTraceFlag.Tests.ps1 b/tests/Unit/Public/Add-SqlDscTraceFlag.Tests.ps1 new file mode 100644 index 000000000..f6ecaae0c --- /dev/null +++ b/tests/Unit/Public/Add-SqlDscTraceFlag.Tests.ps1 @@ -0,0 +1,204 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 2>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:dscModuleName + + # Loading mocked classes + Add-Type -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath '../Stubs') -ChildPath 'SMO.cs') + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscModuleName -All | Remove-Module -Force + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'Add-SqlDscTraceFlag' -Tag 'Public' { + It 'Should have the correct parameters in parameter set ' -ForEach @( + @{ + MockParameterSetName = 'ByServiceObject' + MockExpectedParameters = '-ServiceObject -TraceFlag [-Force] [-WhatIf] [-Confirm] []' + } + @{ + MockParameterSetName = 'ByServerName' + MockExpectedParameters = '-TraceFlag [-ServerName ] [-InstanceName ] [-Force] [-WhatIf] [-Confirm] []' + } + ) { + $result = (Get-Command -Name 'Add-SqlDscTraceFlag').ParameterSets | + Where-Object -FilterScript { + $_.Name -eq $mockParameterSetName + } | + Select-Object -Property @( + @{ + Name = 'ParameterSetName' + Expression = { $_.Name } + }, + @{ + Name = 'ParameterListAsString' + Expression = { $_.ToString() } + } + ) + + $result.ParameterSetName | Should -Be $MockParameterSetName + $result.ParameterListAsString | Should -Be $MockExpectedParameters + } + + Context 'When passing $null as ServiceObject' { + It 'Should throw the correct error' { + $mockErrorMessage = 'Cannot bind argument to parameter ''ServiceObject'' because it is null.' + + { Add-SqlDscTraceFlag -ServiceObject $null } | Should -Throw -ExpectedMessage $mockErrorMessage + } + } + + Context 'When there are no existing trace flags' { + BeforeAll { + Mock -CommandName Set-SqlDscTraceFlag + Mock -CommandName Get-SqlDscTraceFlag -MockWith { + return @() + } + } + + Context 'When adding a trace flag by a service object' { + BeforeAll { + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.Name = 'MSSQL$SQL2022' + } + + Context 'When using parameter Confirm with value $false' { + It 'Should call the mocked method and have correct value in the object' { + { Add-SqlDscTraceFlag -ServiceObject $mockServiceObject -TraceFlag 4199 -Confirm:$false } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscTraceFlag -ParameterFilter { + $TraceFlag -contains 4199 + } -Exactly -Times 1 -Scope It + } + } + + Context 'When using parameter Force' { + It 'Should call the mocked method and have correct value in the object' { + { Add-SqlDscTraceFlag -ServiceObject $mockServiceObject -TraceFlag 4199 -Force } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscTraceFlag -ParameterFilter { + $TraceFlag -contains 4199 + } -Exactly -Times 1 -Scope It + } + } + + Context 'When using parameter WhatIf' { + It 'Should not call the mocked method and should not have changed the value in the object' { + { Add-SqlDscTraceFlag -ServiceObject $mockServiceObject -TraceFlag 4199 -WhatIf } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscTraceFlag -Exactly -Times 0 -Scope It + } + } + + Context 'When passing parameter ServerObject over the pipeline' { + It 'Should call the mocked method and have correct value in the object' { + { $mockServiceObject | Add-SqlDscTraceFlag -TraceFlag 4199 -Force } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscTraceFlag -ParameterFilter { + $TraceFlag -contains 4199 + } -Exactly -Times 1 -Scope It + } + } + } + + Context 'When adding a trace flag by default parameter set and parameters default values' { + Context 'When using parameter Confirm with value $false' { + It 'Should call the mocked method and have correct value in the object' { + { Add-SqlDscTraceFlag -TraceFlag 4199 -Confirm:$false } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscTraceFlag -ParameterFilter { + $TraceFlag -contains 4199 + } -Exactly -Times 1 -Scope It + } + } + + Context 'When using parameter Force' { + It 'Should call the mocked method and have correct value in the object' { + { Add-SqlDscTraceFlag -TraceFlag 4199 -Force } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscTraceFlag -ParameterFilter { + $TraceFlag -contains 4199 + } -Exactly -Times 1 -Scope It + } + } + + Context 'When using parameter WhatIf' { + It 'Should not call the mocked method and should not have changed the value in the object' { + { Add-SqlDscTraceFlag -TraceFlag 4199 -WhatIf } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscTraceFlag -Exactly -Times 0 -Scope It + } + } + } + } + + Context 'When there are an existing trace flag' { + BeforeAll { + Mock -CommandName Set-SqlDscTraceFlag + Mock -CommandName Get-SqlDscTraceFlag -MockWith { + return @(3226) + } + + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.Name = 'MSSQL$SQL2022' + } + + It 'Should call the mocked method and have correct value in the object' { + { Add-SqlDscTraceFlag -ServiceObject $mockServiceObject -TraceFlag 4199 -Force } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscTraceFlag -ParameterFilter { + $TraceFlag.Count -eq 2 -and + $TraceFlag -contains 4199 -and + $TraceFlag -contains 3226 + } -Exactly -Times 1 -Scope It + } + + It 'Should not add duplicate if it already exist' { + { Add-SqlDscTraceFlag -ServiceObject $mockServiceObject -TraceFlag 3226 -Force } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscTraceFlag -ParameterFilter { + $TraceFlag.Count -eq 1 -and + $TraceFlag -contains 3226 + } -Exactly -Times 1 -Scope It + } + } +} diff --git a/tests/Unit/Public/Get-SqlDscAudit.Tests.ps1 b/tests/Unit/Public/Get-SqlDscAudit.Tests.ps1 index 20ddea99a..1d4bb6896 100644 --- a/tests/Unit/Public/Get-SqlDscAudit.Tests.ps1 +++ b/tests/Unit/Public/Get-SqlDscAudit.Tests.ps1 @@ -50,6 +50,31 @@ AfterAll { } Describe 'Get-SqlDscAudit' -Tag 'Public' { + It 'Should have the correct parameters in parameter set ' -ForEach @( + @{ + MockParameterSetName = '__AllParameterSets' + MockExpectedParameters = '[-ServerObject] [-Name] [-Refresh] []' + } + ) { + $result = (Get-Command -Name 'Get-SqlDscAudit').ParameterSets | + Where-Object -FilterScript { + $_.Name -eq $mockParameterSetName + } | + Select-Object -Property @( + @{ + Name = 'ParameterSetName' + Expression = { $_.Name } + }, + @{ + Name = 'ParameterListAsString' + Expression = { $_.ToString() } + } + ) + + $result.ParameterSetName | Should -Be $MockParameterSetName + $result.ParameterListAsString | Should -Be $MockExpectedParameters + } + Context 'When no audit exist' { BeforeAll { $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' | @@ -114,7 +139,7 @@ Describe 'Get-SqlDscAudit' -Tag 'Public' { Context 'When passing parameter ServerObject over the pipeline' { It 'Should return the correct values' { - $result = Get-SqlDscAudit @mockDefaultParameters + $result = $mockServerObject | Get-SqlDscAudit -Name 'Log1' $result | Should -BeOfType 'Microsoft.SqlServer.Management.Smo.Audit' $result.Name | Should -Be 'Log1' diff --git a/tests/Unit/Public/Get-SqlDscManagedComputer.Tests.ps1 b/tests/Unit/Public/Get-SqlDscManagedComputer.Tests.ps1 new file mode 100644 index 000000000..8338f1559 --- /dev/null +++ b/tests/Unit/Public/Get-SqlDscManagedComputer.Tests.ps1 @@ -0,0 +1,89 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 2>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:dscModuleName + + # Loading mocked classes + Add-Type -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath '../Stubs') -ChildPath 'SMO.cs') + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscModuleName -All | Remove-Module -Force + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'Get-SqlDscManagedComputer' -Tag 'Public' { + Context 'When getting the current managed computer' { + BeforeAll { + Mock -CommandName New-Object -ParameterFilter { + $TypeName -eq 'Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer' + } -MockWith { + return 'MockManagedComputer' + } + } + + It 'Should return the correct values' { + $result = Get-SqlDscManagedComputer + + $result | Should -Be 'MockManagedComputer' + + Should -Invoke -CommandName New-Object -Exactly -Times 1 -Scope It + } + } + + Context 'When getting the specified managed computer' { + BeforeAll { + Mock -CommandName New-Object -ParameterFilter { + $TypeName -eq 'Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer' ` + -and $ArgumentList -eq 'localhost' + } -MockWith { + return 'MockManagedComputer' + } + } + + It 'Should return the correct values' { + $result = Get-SqlDscManagedComputer -ServerName 'localhost' + + $result | Should -Be 'MockManagedComputer' + + Should -Invoke -CommandName New-Object -Exactly -Times 1 -Scope It + } + } +} diff --git a/tests/Unit/Public/Get-SqlDscManagedComputerService.Tests.ps1 b/tests/Unit/Public/Get-SqlDscManagedComputerService.Tests.ps1 new file mode 100644 index 000000000..386e3ff4d --- /dev/null +++ b/tests/Unit/Public/Get-SqlDscManagedComputerService.Tests.ps1 @@ -0,0 +1,167 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 2>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:dscModuleName + + # Loading mocked classes + Add-Type -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath '../Stubs') -ChildPath 'SMO.cs') + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscModuleName -All | Remove-Module -Force + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'Get-SqlDscManagedComputerService' -Tag 'Public' { + BeforeAll { + Mock -CommandName Get-SqlDscManagedComputer -MockWith { + return New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer' | + Add-Member -MemberType 'ScriptProperty' -Name 'Services' -Value { + return @( + @{ + Name = 'SQLBrowser' + Type = 'SqlBrowser' + } + @{ + Name = 'MSSQL$SQL2022' + Type = 'SqlServer' + } + @{ + Name = 'MSSQLSERVER' + Type = 'SqlServer' + } + ) + } -PassThru -Force + } + } + + Context 'When getting all the services on the current managed computer' { + It 'Should return the correct values' { + $result = Get-SqlDscManagedComputerService + + $result | Should -HaveCount 3 + $result.Name | Should -Contain 'MSSQL$SQL2022' + $result.Name | Should -Contain 'SQLBrowser' + $result.Name | Should -Contain 'MSSQLSERVER' + + Should -Invoke -CommandName Get-SqlDscManagedComputer -Exactly -Times 1 -Scope It + } + } + + Context 'When getting all the services on the specified managed computer' { + It 'Should return the correct values' { + $result = Get-SqlDscManagedComputerService -ServerName 'localhost' + + $result | Should -HaveCount 3 + $result.Name | Should -Contain 'MSSQL$SQL2022' + $result.Name | Should -Contain 'SQLBrowser' + $result.Name | Should -Contain 'MSSQLSERVER' + + Should -Invoke -CommandName Get-SqlDscManagedComputer -Exactly -Times 1 -Scope It + } + + Context 'When passing parameter ManagedComputerObject over the pipeline' { + It 'Should return the correct values' { + $managedComputerObject1 = [Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer]::new('localhost') + + $managedComputerObject1 | + Add-Member -MemberType 'ScriptProperty' -Name 'Services' -Value { + return @( + @{ + Name = 'SQLBrowser' + Type = 'SqlBrowser' + } + @{ + Name = 'MSSQL$SQL2022' + Type = 'SqlServer' + } + ) + } -PassThru -Force + + $managedComputerObject2 = [Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer]::new('localhost') + + $managedComputerObject2 | + Add-Member -MemberType 'ScriptProperty' -Name 'Services' -Value { + return @( + @{ + Name = 'MSSQLSERVER' + Type = 'SqlServer' + } + ) + } -PassThru -Force + + $result = @( + $managedComputerObject1 + $managedComputerObject2 + ) | Get-SqlDscManagedComputerService + + $result | Should -HaveCount 3 + $result.Name | Should -Contain 'MSSQL$SQL2022' + $result.Name | Should -Contain 'SQLBrowser' + $result.Name | Should -Contain 'MSSQLSERVER' + + Should -Invoke -CommandName Get-SqlDscManagedComputer -Exactly -Times 0 -Scope It + } + } + } + + Context 'When getting a specific services' { + It 'Should return the correct values' { + $result = Get-SqlDscManagedComputerService -ServiceType 'DatabaseEngine' + + $result | Should -HaveCount 2 + $result.Name | Should -Contain 'MSSQL$SQL2022' + $result.Name | Should -Contain 'MSSQLSERVER' + + Should -Invoke -CommandName Get-SqlDscManagedComputer -Exactly -Times 1 -Scope It + } + } + + Context 'When getting a specific instance' { + It 'Should return the correct values' { + $result = Get-SqlDscManagedComputerService -InstanceName 'SQL2022' + + $result | Should -HaveCount 1 + $result.Name | Should -Contain 'MSSQL$SQL2022' + + Should -Invoke -CommandName Get-SqlDscManagedComputer -Exactly -Times 1 -Scope It + } + } +} diff --git a/tests/Unit/Public/Get-SqlDscStartupParameter.Tests.ps1 b/tests/Unit/Public/Get-SqlDscStartupParameter.Tests.ps1 new file mode 100644 index 000000000..1c94b59bc --- /dev/null +++ b/tests/Unit/Public/Get-SqlDscStartupParameter.Tests.ps1 @@ -0,0 +1,285 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 2>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:dscModuleName + + # Loading mocked classes + Add-Type -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath '../Stubs') -ChildPath 'SMO.cs') + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscModuleName -All | Remove-Module -Force + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'Get-SqlDscStartupParameter' -Tag 'Public' { + It 'Should have the correct parameters in parameter set ' -ForEach @( + @{ + MockParameterSetName = 'ByServiceObject' + MockExpectedParameters = '-ServiceObject []' + } + @{ + MockParameterSetName = 'ByServerName' + MockExpectedParameters = '[-ServerName ] [-InstanceName ] []' + } + ) { + $result = (Get-Command -Name 'Get-SqlDscStartupParameter').ParameterSets | + Where-Object -FilterScript { + $_.Name -eq $mockParameterSetName + } | + Select-Object -Property @( + @{ + Name = 'ParameterSetName' + Expression = { $_.Name } + }, + @{ + Name = 'ParameterListAsString' + Expression = { $_.ToString() } + } + ) + + $result.ParameterSetName | Should -Be $MockParameterSetName + $result.ParameterListAsString | Should -Be $MockExpectedParameters + } + + Context 'When passing $null as ServiceObject' { + It 'Should throw the correct error' { + $mockErrorMessage = 'Cannot bind argument to parameter ''ServiceObject'' because it is null.' + + { Get-SqlDscStartupParameter -ServiceObject $null } | Should -Throw -ExpectedMessage $mockErrorMessage + } + } + + Context 'When passing a ServiceObject with wrong service type' { + BeforeAll { + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.Type = 'SqlAgent' + + Mock -CommandName Assert-ElevatedUser + } + + Context 'When passing the value Stop for parameter ErrorAction' { + It 'Should throw the correct error' { + $mockErrorMessage = InModuleScope -ScriptBlock { + $script:localizedData.TraceFlag_Get_WrongServiceType + } + + $mockErrorMessage = $mockErrorMessage -f 'SqlServer', 'SqlAgent' + + { Get-SqlDscStartupParameter -ServiceObject $mockServiceObject -ErrorAction 'Stop' } | + Should -Throw -ExpectedMessage $mockErrorMessage + } + } + + Context 'When passing the value SilentlyContinue for parameter ErrorAction' { + It 'Should still throw the correct terminating error' { + $mockErrorMessage = InModuleScope -ScriptBlock { + $script:localizedData.TraceFlag_Get_WrongServiceType + } + + $mockErrorMessage = $mockErrorMessage -f 'SqlServer', 'SqlAgent' + + { Get-SqlDscStartupParameter -ServiceObject $mockServiceObject -ErrorAction 'SilentlyContinue' } | + Should -Throw -ExpectedMessage $mockErrorMessage + } + } + } + + Context 'When passing server name but an Managed Computer Service object is not returned' { + BeforeAll { + Mock -CommandName Assert-ElevatedUser + + Mock -CommandName Get-SqlDscManagedComputerService -MockWith { + return $null + } + } + + Context 'When passing SilentlyContinue to ErrorAction' { + It 'Should not throw and return an empty array' { + $result = Get-SqlDscStartupParameter -ServerName 'localhost' -ErrorAction 'SilentlyContinue' + + $result | Should -BeNullOrEmpty + + Should -Invoke -CommandName Get-SqlDscManagedComputerService -Exactly -Times 1 -Scope It + } + } + + Context 'When passing Stop to ErrorAction' { + It 'Should throw the correct error' { + $mockErrorMessage = InModuleScope -ScriptBlock { + $script:localizedData.TraceFlag_Get_FailedToFindServiceObject + } + + { Get-SqlDscStartupParameter -ServerName 'localhost' -ErrorAction 'Stop' } | Should -Throw -ExpectedMessage $mockErrorMessage + + Should -Invoke -CommandName Get-SqlDscManagedComputerService -Exactly -Times 1 -Scope It + } + } + } + + Context 'When only default startup parameters exist' { + BeforeAll { + $mockStartupParameters = '-dC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf;-eC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG;-lC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf' + + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.StartupParameters = $mockStartupParameters + $mockServiceObject.Type = 'SqlServer' + + Mock -CommandName Assert-ElevatedUser + + Mock -CommandName Get-SqlDscManagedComputerService -MockWith { + return $mockServiceObject + } + } + + Context 'When passing no parameters' { + It 'Should return an empty array' { + $result = Get-SqlDscStartupParameter + + Should -ActualValue $result -BeOfType (InModuleScope -ScriptBlock { [StartupParameters] }) + + Should -ActualValue $result.TraceFlag -BeOfType 'System.UInt32[]' + Should -ActualValue $result.DataFilePath -BeOfType 'System.String[]' + Should -ActualValue $result.LogFilePath -BeOfType 'System.String[]' + Should -ActualValue $result.ErrorLogPath -BeOfType 'System.String[]' + + $result.DataFilePath | Should -Be 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf' + $result.LogFilePath | Should -Be 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf' + $result.ErrorLogPath | Should -Be 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG' + $result.TraceFlag | Should -BeNullOrEmpty + + Should -Invoke -CommandName Get-SqlDscManagedComputerService -Exactly -Times 1 -Scope It + } + } + + Context 'When passing specific server name' { + It 'Should return an empty array' { + $result = Get-SqlDscStartupParameter -ServerName 'localhost' + + Should -ActualValue $result -BeOfType (InModuleScope -ScriptBlock { [StartupParameters] }) + + Should -ActualValue $result.TraceFlag -BeOfType 'System.UInt32[]' + Should -ActualValue $result.DataFilePath -BeOfType 'System.String[]' + Should -ActualValue $result.LogFilePath -BeOfType 'System.String[]' + Should -ActualValue $result.ErrorLogPath -BeOfType 'System.String[]' + + $result.DataFilePath | Should -Be 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf' + $result.LogFilePath | Should -Be 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf' + $result.ErrorLogPath | Should -Be 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG' + $result.TraceFlag | Should -BeNullOrEmpty + + Should -Invoke -CommandName Get-SqlDscManagedComputerService -ParameterFilter { + $ServerName -eq 'localhost' + } -Exactly -Times 1 -Scope It + } + } + + Context 'When passing specific instance name' { + It 'Should return an empty array' { + $result = Get-SqlDscStartupParameter -InstanceName 'SQL2022' + + Should -ActualValue $result -BeOfType (InModuleScope -ScriptBlock { [StartupParameters] }) + + Should -ActualValue $result.TraceFlag -BeOfType 'System.UInt32[]' + Should -ActualValue $result.DataFilePath -BeOfType 'System.String[]' + Should -ActualValue $result.LogFilePath -BeOfType 'System.String[]' + Should -ActualValue $result.ErrorLogPath -BeOfType 'System.String[]' + + $result.DataFilePath | Should -Be 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf' + $result.LogFilePath | Should -Be 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf' + $result.ErrorLogPath | Should -Be 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG' + $result.TraceFlag | Should -BeNullOrEmpty + + Should -Invoke -CommandName Get-SqlDscManagedComputerService -ParameterFilter { + $InstanceName -eq 'SQL2022' + } -Exactly -Times 1 -Scope It + } + } + + Context 'When passing a service object' { + It 'Should return an empty array' { + $result = Get-SqlDscStartupParameter -ServiceObject $mockServiceObject + + Should -ActualValue $result -BeOfType (InModuleScope -ScriptBlock { [StartupParameters] }) + + Should -ActualValue $result.TraceFlag -BeOfType 'System.UInt32[]' + Should -ActualValue $result.DataFilePath -BeOfType 'System.String[]' + Should -ActualValue $result.LogFilePath -BeOfType 'System.String[]' + Should -ActualValue $result.ErrorLogPath -BeOfType 'System.String[]' + + $result.DataFilePath | Should -Be 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf' + $result.LogFilePath | Should -Be 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf' + $result.ErrorLogPath | Should -Be 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG' + $result.TraceFlag | Should -BeNullOrEmpty + + Should -Invoke -CommandName Get-SqlDscManagedComputerService -Exactly -Times 0 -Scope It + } + } + } + + Context 'When one trace flag exist' { + BeforeAll { + $mockStartupParameters = '-dC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf;-eC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG;-lC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf;-T4199' + + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.StartupParameters = $mockStartupParameters + $mockServiceObject.Type = 'SqlServer' + + Mock -CommandName Assert-ElevatedUser + } + + It 'Should return the correct values' { + $result = Get-SqlDscStartupParameter -ServiceObject $mockServiceObject + + Should -ActualValue $result -BeOfType (InModuleScope -ScriptBlock { [StartupParameters] }) + + Should -ActualValue $result.TraceFlag -BeOfType 'System.UInt32[]' + Should -ActualValue $result.DataFilePath -BeOfType 'System.String[]' + Should -ActualValue $result.LogFilePath -BeOfType 'System.String[]' + Should -ActualValue $result.ErrorLogPath -BeOfType 'System.String[]' + + $result.DataFilePath | Should -Be 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf' + $result.LogFilePath | Should -Be 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf' + $result.ErrorLogPath | Should -Be 'C:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG' + $result.TraceFlag | Should -HaveCount 1 + $result.TraceFlag | Should -Contain 4199 + } + } +} diff --git a/tests/Unit/Public/Get-SqlDscTraceFlag.Tests.ps1 b/tests/Unit/Public/Get-SqlDscTraceFlag.Tests.ps1 new file mode 100644 index 000000000..0af0a0df0 --- /dev/null +++ b/tests/Unit/Public/Get-SqlDscTraceFlag.Tests.ps1 @@ -0,0 +1,305 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 2>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:dscModuleName + + # Loading mocked classes + Add-Type -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath '../Stubs') -ChildPath 'SMO.cs') + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscModuleName -All | Remove-Module -Force + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'Get-SqlDscTraceFlag' -Tag 'Public' { + It 'Should have the correct parameters in parameter set ' -ForEach @( + @{ + MockParameterSetName = 'ByServiceObject' + MockExpectedParameters = '-ServiceObject []' + } + @{ + MockParameterSetName = 'ByServerName' + MockExpectedParameters = '[-ServerName ] [-InstanceName ] []' + } + ) { + $result = (Get-Command -Name 'Get-SqlDscTraceFlag').ParameterSets | + Where-Object -FilterScript { + $_.Name -eq $mockParameterSetName + } | + Select-Object -Property @( + @{ + Name = 'ParameterSetName' + Expression = { $_.Name } + }, + @{ + Name = 'ParameterListAsString' + Expression = { $_.ToString() } + } + ) + + $result.ParameterSetName | Should -Be $MockParameterSetName + $result.ParameterListAsString | Should -Be $MockExpectedParameters + } + + Context 'When passing $null as ServiceObject' { + It 'Should throw the correct error' { + $mockErrorMessage = 'Cannot bind argument to parameter ''ServiceObject'' because it is null.' + + { Get-SqlDscTraceFlag -ServiceObject $null } | Should -Throw -ExpectedMessage $mockErrorMessage + } + } + + Context 'When no trace flag exist' { + BeforeAll { + Mock -CommandName Get-SqlDscStartupParameter -MockWith { + return @{ + TraceFlag = @() + } + } + } + + Context 'When passing no parameters' { + It 'Should return an empty array' { + $result = Get-SqlDscTraceFlag + + Should -ActualValue $result -BeOfType 'System.UInt32[]' + + $result | Should -BeNullOrEmpty + + Should -Invoke -CommandName Get-SqlDscStartupParameter -Exactly -Times 1 -Scope It + } + } + + Context 'When passing specific server name' { + It 'Should return an empty array' { + $result = Get-SqlDscTraceFlag -ServerName 'localhost' + + Should -ActualValue $result -BeOfType 'System.UInt32[]' + + $result | Should -BeNullOrEmpty + + Should -Invoke -CommandName Get-SqlDscStartupParameter -ParameterFilter { + $ServerName -eq 'localhost' + } -Exactly -Times 1 -Scope It + } + } + + Context 'When passing specific instance name' { + It 'Should return an empty array' { + $result = Get-SqlDscTraceFlag -InstanceName 'SQL2022' + + Should -ActualValue $result -BeOfType 'System.UInt32[]' + + $result | Should -BeNullOrEmpty + + Should -Invoke -CommandName Get-SqlDscStartupParameter -ParameterFilter { + $InstanceName -eq 'SQL2022' + } -Exactly -Times 1 -Scope It + } + } + + Context 'When passing a service object' { + It 'Should return an empty array' { + $mockStartupParameters = '-dC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf;-eC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG;-lC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf' + + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.StartupParameters = $mockStartupParameters + $mockServiceObject.Type = 'SqlServer' + + $result = Get-SqlDscTraceFlag -ServiceObject $mockServiceObject + + Should -ActualValue $result -BeOfType 'System.UInt32[]' + + $result | Should -BeNullOrEmpty + + Should -Invoke -CommandName Get-SqlDscStartupParameter -Exactly -Times 1 -Scope It + } + } + } + + Context 'When one trace flag exist' { + BeforeAll { + Mock -CommandName Get-SqlDscStartupParameter -MockWith { + return @{ + TraceFlag = @(4199) + } + } + } + + Context 'When passing no parameters' { + It 'Should return the correct values' { + $result = Get-SqlDscTraceFlag + + Should -ActualValue $result -BeOfType 'System.UInt32[]' + + $result | Should -HaveCount 1 + $result | Should -Contain 4199 + + Should -Invoke -CommandName Get-SqlDscStartupParameter -Exactly -Times 1 -Scope It + } + } + + Context 'When passing specific server name' { + It 'Should return the correct values' { + $result = Get-SqlDscTraceFlag -ServerName 'localhost' + + Should -ActualValue $result -BeOfType 'System.UInt32[]' + + $result | Should -HaveCount 1 + $result | Should -Contain 4199 + + Should -Invoke -CommandName Get-SqlDscStartupParameter -ParameterFilter { + $ServerName -eq 'localhost' + } -Exactly -Times 1 -Scope It + } + } + + Context 'When passing specific instance name' { + It 'Should return the correct values' { + $result = Get-SqlDscTraceFlag -InstanceName 'SQL2022' + + Should -ActualValue $result -BeOfType 'System.UInt32[]' + + $result | Should -HaveCount 1 + $result | Should -Contain 4199 + + Should -Invoke -CommandName Get-SqlDscStartupParameter -ParameterFilter { + $InstanceName -eq 'SQL2022' + } -Exactly -Times 1 -Scope It + } + } + + Context 'When passing a service object' { + It 'Should return the correct values' { + $mockStartupParameters = '-dC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf;-eC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG;-lC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf;-T4199' + + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.StartupParameters = $mockStartupParameters + $mockServiceObject.Type = 'SqlServer' + + $result = Get-SqlDscTraceFlag -ServiceObject $mockServiceObject + + Should -ActualValue $result -BeOfType 'System.UInt32[]' + + $result | Should -HaveCount 1 + $result | Should -Contain 4199 + + Should -Invoke -CommandName Get-SqlDscStartupParameter -Exactly -Times 1 -Scope It + } + } + } + + Context 'When multiple trace flag exist' { + BeforeAll { + Mock -CommandName Get-SqlDscStartupParameter -MockWith { + return @{ + TraceFlag = @(4199, 3226) + } + } + } + + Context 'When passing no parameters' { + It 'Should return the correct values' { + $result = Get-SqlDscTraceFlag + + Should -ActualValue $result -BeOfType 'System.UInt32[]' + + $result | Should -HaveCount 2 + $result | Should -Contain 4199 + $result | Should -Contain 3226 + + Should -Invoke -CommandName Get-SqlDscStartupParameter -Exactly -Times 1 -Scope It + } + } + + Context 'When passing specific server name' { + It 'Should return the correct values' { + $result = Get-SqlDscTraceFlag -ServerName 'localhost' + + Should -ActualValue $result -BeOfType 'System.UInt32[]' + + $result | Should -HaveCount 2 + $result | Should -Contain 4199 + $result | Should -Contain 3226 + + Should -Invoke -CommandName Get-SqlDscStartupParameter -ParameterFilter { + $ServerName -eq 'localhost' + } -Exactly -Times 1 -Scope It + } + } + + Context 'When passing specific instance name' { + It 'Should return the correct values' { + $result = Get-SqlDscTraceFlag -InstanceName 'SQL2022' + + Should -ActualValue $result -BeOfType 'System.UInt32[]' + + $result | Should -HaveCount 2 + $result | Should -Contain 4199 + $result | Should -Contain 3226 + + Should -Invoke -CommandName Get-SqlDscStartupParameter -ParameterFilter { + $InstanceName -eq 'SQL2022' + } -Exactly -Times 1 -Scope It + } + } + + Context 'When passing a service object' { + It 'Should return the correct values' { + $mockStartupParameters = '-dC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf;-eC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG;-lC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf;-T4199;-T3226' + + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.StartupParameters = $mockStartupParameters + $mockServiceObject.Type = 'SqlServer' + + $result = Get-SqlDscTraceFlag -ServiceObject $mockServiceObject + + Should -ActualValue $result -BeOfType 'System.UInt32[]' + + $result | Should -HaveCount 2 + $result | Should -Contain 4199 + $result | Should -Contain 3226 + + Should -Invoke -CommandName Get-SqlDscStartupParameter -Exactly -Times 1 -Scope It + } + } + } +} diff --git a/tests/Unit/Public/Remove-SqlDscTraceFlag.Tests.ps1 b/tests/Unit/Public/Remove-SqlDscTraceFlag.Tests.ps1 new file mode 100644 index 000000000..1ef7ce57f --- /dev/null +++ b/tests/Unit/Public/Remove-SqlDscTraceFlag.Tests.ps1 @@ -0,0 +1,232 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 2>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:dscModuleName + + # Loading mocked classes + Add-Type -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath '../Stubs') -ChildPath 'SMO.cs') + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscModuleName -All | Remove-Module -Force + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'Remove-SqlDscTraceFlag' -Tag 'Public' { + It 'Should have the correct parameters in parameter set ' -ForEach @( + @{ + MockParameterSetName = 'ByServiceObject' + MockExpectedParameters = '-ServiceObject -TraceFlag [-Force] [-WhatIf] [-Confirm] []' + } + @{ + MockParameterSetName = 'ByServerName' + MockExpectedParameters = '-TraceFlag [-ServerName ] [-InstanceName ] [-Force] [-WhatIf] [-Confirm] []' + } + ) { + $result = (Get-Command -Name 'Remove-SqlDscTraceFlag').ParameterSets | + Where-Object -FilterScript { + $_.Name -eq $mockParameterSetName + } | + Select-Object -Property @( + @{ + Name = 'ParameterSetName' + Expression = { $_.Name } + }, + @{ + Name = 'ParameterListAsString' + Expression = { $_.ToString() } + } + ) + + $result.ParameterSetName | Should -Be $MockParameterSetName + $result.ParameterListAsString | Should -Be $MockExpectedParameters + } + + Context 'When passing $null as ServiceObject' { + It 'Should throw the correct error' { + $mockErrorMessage = 'Cannot bind argument to parameter ''ServiceObject'' because it is null.' + + { Remove-SqlDscTraceFlag -ServiceObject $null } | Should -Throw -ExpectedMessage $mockErrorMessage + } + } + + Context 'When there are an existing trace flag' { + BeforeAll { + Mock -CommandName Set-SqlDscTraceFlag + Mock -CommandName Get-SqlDscTraceFlag -MockWith { + return @(4199) + } + } + + Context 'When removing a trace flag by a service object' { + BeforeAll { + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.Name = 'MSSQL$SQL2022' + } + + Context 'When using parameter Confirm with value $false' { + It 'Should call the mocked method and have correct value in the object' { + { Remove-SqlDscTraceFlag -ServiceObject $mockServiceObject -TraceFlag 4199 -Confirm:$false } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscTraceFlag -ParameterFilter { + $TraceFlag.Count -eq 0 + } -Exactly -Times 1 -Scope It + } + } + + Context 'When using parameter Force' { + It 'Should call the mocked method and have correct value in the object' { + { Remove-SqlDscTraceFlag -ServiceObject $mockServiceObject -TraceFlag 4199 -Force } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscTraceFlag -ParameterFilter { + $TraceFlag.Count -eq 0 + } -Exactly -Times 1 -Scope It + } + } + + Context 'When using parameter WhatIf' { + It 'Should not call the mocked method and should not have changed the value in the object' { + { Remove-SqlDscTraceFlag -ServiceObject $mockServiceObject -TraceFlag 4199 -WhatIf } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscTraceFlag -Exactly -Times 0 -Scope It + } + } + + Context 'When passing parameter ServerObject over the pipeline' { + It 'Should call the mocked method and have correct value in the object' { + { $mockServiceObject | Remove-SqlDscTraceFlag -TraceFlag 4199 -Force } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscTraceFlag -ParameterFilter { + $TraceFlag.Count -eq 0 + } -Exactly -Times 1 -Scope It + } + } + } + + Context 'When removing a trace flag by default parameter set and parameters default values' { + Context 'When using parameter Confirm with value $false' { + It 'Should call the mocked method and have correct value in the object' { + { Remove-SqlDscTraceFlag -TraceFlag 4199 -Confirm:$false } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscTraceFlag -ParameterFilter { + $TraceFlag.Count -eq 0 + } -Exactly -Times 1 -Scope It + } + } + + Context 'When using parameter Force' { + It 'Should call the mocked method and have correct value in the object' { + { Remove-SqlDscTraceFlag -TraceFlag 4199 -Force } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscTraceFlag -ParameterFilter { + $TraceFlag.Count -eq 0 + } -Exactly -Times 1 -Scope It + } + } + + Context 'When using parameter WhatIf' { + It 'Should not call the mocked method and should not have changed the value in the object' { + { Remove-SqlDscTraceFlag -TraceFlag 4199 -WhatIf } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscTraceFlag -Exactly -Times 0 -Scope It + } + } + } + + Context 'When the trace flag to remove does not exist' { + BeforeAll { + Mock -CommandName Get-SqlDscTraceFlag -MockWith { + return @(4199) + } + + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.Name = 'MSSQL$SQL2022' + } + + It 'Should call the mocked method and have correct value in the object' { + { Remove-SqlDscTraceFlag -ServiceObject $mockServiceObject -TraceFlag 3226 -Force } | Should -Not -Throw + + # Should still re-set the existing trace flag. + Should -Invoke -CommandName Set-SqlDscTraceFlag -ParameterFilter { + $TraceFlag -contains 4199 + } -Exactly -Times 1 -Scope It + } + } + } + + Context 'When there are no existing trace flags' { + BeforeAll { + Mock -CommandName Set-SqlDscTraceFlag + Mock -CommandName Get-SqlDscTraceFlag -MockWith { + return @() + } + + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.Name = 'MSSQL$SQL2022' + } + + It 'Should call the mocked method and have correct value in the object' { + { Remove-SqlDscTraceFlag -ServiceObject $mockServiceObject -TraceFlag 4199 -Force } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscTraceFlag -Exactly -Times 0 -Scope It + } + } + + Context 'When there are trace flags left after the removal' { + BeforeAll { + Mock -CommandName Set-SqlDscTraceFlag + Mock -CommandName Get-SqlDscTraceFlag -MockWith { + return @(4199, 3226) + } + + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.Name = 'MSSQL$SQL2022' + } + + It 'Should call the mocked method and have correct value in the object' { + { Remove-SqlDscTraceFlag -ServiceObject $mockServiceObject -TraceFlag 3226 -Force } | Should -Not -Throw + + # Should still re-set the existing trace flag. + Should -Invoke -CommandName Set-SqlDscTraceFlag -ParameterFilter { + $TraceFlag -contains 4199 + } -Exactly -Times 1 -Scope It + } + } +} diff --git a/tests/Unit/Public/Set-SqlDscStartupParameter.Tests.ps1 b/tests/Unit/Public/Set-SqlDscStartupParameter.Tests.ps1 new file mode 100644 index 000000000..15a4d69e5 --- /dev/null +++ b/tests/Unit/Public/Set-SqlDscStartupParameter.Tests.ps1 @@ -0,0 +1,378 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 2>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:dscModuleName + + # Loading mocked classes + Add-Type -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath '../Stubs') -ChildPath 'SMO.cs') + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscModuleName -All | Remove-Module -Force + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'Set-SqlDscStartupParameter' -Tag 'Public' { + It 'Should have the correct parameters in parameter set ' -ForEach @( + @{ + MockParameterSetName = 'ByServiceObject' + MockExpectedParameters = '-ServiceObject [-TraceFlag ] [-InternalTraceFlag ] [-Force] [-WhatIf] [-Confirm] []' + } + @{ + MockParameterSetName = 'ByServerName' + MockExpectedParameters = '[-ServerName ] [-InstanceName ] [-TraceFlag ] [-InternalTraceFlag ] [-Force] [-WhatIf] [-Confirm] []' + } + ) { + $result = (Get-Command -Name 'Set-SqlDscStartupParameter').ParameterSets | + Where-Object -FilterScript { + $_.Name -eq $mockParameterSetName + } | + Select-Object -Property @( + @{ + Name = 'ParameterSetName' + Expression = { $_.Name } + }, + @{ + Name = 'ParameterListAsString' + Expression = { $_.ToString() } + } + ) + + $result.ParameterSetName | Should -Be $MockParameterSetName + $result.ParameterListAsString | Should -Be $MockExpectedParameters + } + + Context 'When passing $null as ServiceObject' { + It 'Should throw the correct error' { + $mockErrorMessage = 'Cannot bind argument to parameter ''ServiceObject'' because it is null.' + + { Set-SqlDscStartupParameter -ServiceObject $null } | Should -Throw -ExpectedMessage $mockErrorMessage + } + } + + Context 'When passing a ServiceObject with wrong service type' { + BeforeAll { + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.Type = 'SqlAgent' + + Mock -CommandName Assert-ElevatedUser + } + + Context 'When passing the value Stop for parameter ErrorAction' { + It 'Should throw the correct error' { + $mockErrorMessage = InModuleScope -ScriptBlock { + $script:localizedData.TraceFlag_Set_WrongServiceType + } + + $mockErrorMessage = $mockErrorMessage -f 'SqlServer', 'SqlAgent' + + { Set-SqlDscStartupParameter -ServiceObject $mockServiceObject -TraceFlag @() -ErrorAction 'Stop' } | + Should -Throw -ExpectedMessage $mockErrorMessage + } + } + + Context 'When passing the value SilentlyContinue for parameter ErrorAction' { + It 'Should still throw the correct terminating error' { + $mockErrorMessage = InModuleScope -ScriptBlock { + $script:localizedData.TraceFlag_Get_WrongServiceType + } + + $mockErrorMessage = $mockErrorMessage -f 'SqlServer', 'SqlAgent' + + { Set-SqlDscStartupParameter -ServiceObject $mockServiceObject -TraceFlag @() -ErrorAction 'SilentlyContinue' } | + Should -Throw -ExpectedMessage $mockErrorMessage + } + } + } + + Context 'When passing server name but an Managed Computer Service object is not returned' { + BeforeAll { + Mock -CommandName Assert-ElevatedUser + + Mock -CommandName Get-SqlDscManagedComputerService -MockWith { + return $null + } + } + + Context 'When passing SilentlyContinue to ErrorAction' { + It 'Should not throw ' { + { Set-SqlDscStartupParameter -ServerName 'localhost' -TraceFlag @() -ErrorAction 'SilentlyContinue' } | Should -Not -Throw + + Should -Invoke -CommandName Get-SqlDscManagedComputerService -Exactly -Times 1 -Scope It + } + } + + Context 'When passing Stop to ErrorAction' { + It 'Should return an empty array' { + $mockErrorMessage = InModuleScope -ScriptBlock { + $script:localizedData.TraceFlag_Set_FailedToFindServiceObject + } + + { Set-SqlDscStartupParameter -ServerName 'localhost' -TraceFlag @() -ErrorAction 'Stop' } | Should -Throw -ExpectedMessage $mockErrorMessage + + Should -Invoke -CommandName Get-SqlDscManagedComputerService -Exactly -Times 1 -Scope It + } + } + } + + Context 'When setting a trace flag by a service object' { + BeforeAll { + $mockStartupParameters = '-dC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf;-eC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG;-lC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf' + + Mock -CommandName Assert-ElevatedUser + } + + BeforeEach { + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.Name = 'MSSQL$SQL2022' + $mockServiceObject.StartupParameters = $mockStartupParameters + $mockServiceObject.Type = 'SqlServer' + + $mockServiceObject | + Add-Member -MemberType 'ScriptMethod' -Name 'Alter' -Value { + $script:mockMethodAlterCallCount += 1 + } -PassThru -Force + + $script:mockMethodAlterCallCount = 0 + } + + Context 'When using parameter Confirm with value $false' { + It 'Should call the mocked method and have correct value in the object' { + { Set-SqlDscStartupParameter -ServiceObject $mockServiceObject -TraceFlag 4199 -Confirm:$false } | Should -Not -Throw + + # This is the object created by the mock and modified by the command. + $mockServiceObject.StartupParameters | Should -BeExactly ($mockStartupParameters + ';-T4199') + + $mockMethodAlterCallCount | Should -Be 1 + } + } + + Context 'When using parameter Force' { + It 'Should call the mocked method and have correct value in the object' { + { Set-SqlDscStartupParameter -ServiceObject $mockServiceObject -TraceFlag 4199 -Force } | Should -Not -Throw + + # This is the object created by the mock and modified by the command. + $mockServiceObject.StartupParameters | Should -BeExactly ($mockStartupParameters + ';-T4199') + + $mockMethodAlterCallCount | Should -Be 1 + } + } + + Context 'When using parameter WhatIf' { + It 'Should not call the mocked method and should not have changed the value in the object' { + { Set-SqlDscStartupParameter -ServiceObject $mockServiceObject -TraceFlag 4199 -WhatIf } | Should -Not -Throw + + # This is the object created by the mock and modified by the command. + $mockServiceObject.StartupParameters | Should -BeExactly $mockStartupParameters + + $mockMethodAlterCallCount | Should -Be 0 + } + } + + Context 'When passing parameter ServerObject over the pipeline' { + It 'Should call the mocked method and have correct value in the object' { + { $mockServiceObject | Set-SqlDscStartupParameter -TraceFlag 4199 -Force } | Should -Not -Throw + + # This is the object created by the mock and modified by the command. + $mockServiceObject.StartupParameters | Should -BeExactly ($mockStartupParameters + ';-T4199') + + $mockMethodAlterCallCount | Should -Be 1 + } + } + } + + Context 'When setting a trace flag by default parameter set and parameters default values' { + BeforeAll { + $mockStartupParameters = '-dC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf;-eC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG;-lC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf' + + Mock -CommandName Assert-ElevatedUser + Mock -CommandName Get-SqlDscManagedComputerService -MockWith { + return $mockServiceObject + } + } + + BeforeEach { + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.StartupParameters = $mockStartupParameters + $mockServiceObject.Type = 'SqlServer' + + $mockServiceObject | + Add-Member -MemberType 'ScriptMethod' -Name 'Alter' -Value { + $script:mockMethodAlterCallCount += 1 + } -PassThru -Force + + $script:mockMethodAlterCallCount = 0 + } + + Context 'When using parameter Confirm with value $false' { + It 'Should call the mocked method and have correct value in the object' { + { Set-SqlDscStartupParameter -TraceFlag 4199 -Confirm:$false } | Should -Not -Throw + + # This is the object created by the mock and modified by the command. + $mockServiceObject.StartupParameters | Should -BeExactly ($mockStartupParameters + ';-T4199') + + $mockMethodAlterCallCount | Should -Be 1 + } + } + + Context 'When using parameter Force' { + It 'Should call the mocked method and have correct value in the object' { + { Set-SqlDscStartupParameter -TraceFlag 4199 -Force } | Should -Not -Throw + + # This is the object created by the mock and modified by the command. + $mockServiceObject.StartupParameters | Should -BeExactly ($mockStartupParameters + ';-T4199') + + $mockMethodAlterCallCount | Should -Be 1 + } + } + + Context 'When using parameter WhatIf' { + It 'Should not call the mocked method and should not have changed the value in the object' { + { Set-SqlDscStartupParameter -TraceFlag 4199 -WhatIf } | Should -Not -Throw + + # This is the object created by the mock and modified by the command. + $mockServiceObject.StartupParameters | Should -BeExactly $mockStartupParameters + + $mockMethodAlterCallCount | Should -Be 0 + } + } + } + + Context 'When clearing all trace flags' { + BeforeAll { + $mockStartupParameters = '-dC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf;-eC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG;-lC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf;-T4199;-T3226' + $mockExpectedStartupParameters = $mockStartupParameters -replace ';-T4199;-T3226' + + Mock -CommandName Assert-ElevatedUser + Mock -CommandName Get-SqlDscManagedComputerService -MockWith { + return $mockServiceObject + } + } + + BeforeEach { + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.StartupParameters = $mockStartupParameters + $mockServiceObject.Type = 'SqlServer' + + $mockServiceObject | + Add-Member -MemberType 'ScriptMethod' -Name 'Alter' -Value { + $script:mockMethodAlterCallCount += 1 + } -PassThru -Force + + $script:mockMethodAlterCallCount = 0 + } + + It 'Should call the mocked method and have correct value in the object' { + { Set-SqlDscStartupParameter -TraceFlag @() -Force } | Should -Not -Throw + + # This is the object created by the mock and modified by the command. + $mockServiceObject.StartupParameters | Should -BeExactly $mockExpectedStartupParameters + + $mockMethodAlterCallCount | Should -Be 1 + } + } + + Context 'When setting a internal trace flag by default parameter set and parameters default values' { + BeforeAll { + $mockStartupParameters = '-dC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf;-eC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG;-lC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf' + + Mock -CommandName Assert-ElevatedUser + Mock -CommandName Get-SqlDscManagedComputerService -MockWith { + return $mockServiceObject + } + } + + BeforeEach { + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.StartupParameters = $mockStartupParameters + $mockServiceObject.Type = 'SqlServer' + + $mockServiceObject | + Add-Member -MemberType 'ScriptMethod' -Name 'Alter' -Value { + $script:mockMethodAlterCallCount += 1 + } -PassThru -Force + + $script:mockMethodAlterCallCount = 0 + } + + It 'Should call the mocked method and have correct value in the object' { + { Set-SqlDscStartupParameter -InternalTraceFlag 8688 -Confirm:$false } | Should -Not -Throw + + # This is the object created by the mock and modified by the command. + $mockServiceObject.StartupParameters | Should -BeExactly ($mockStartupParameters + ';-t8688') + + $mockMethodAlterCallCount | Should -Be 1 + } + } + + Context 'When clearing all internal trace flags' { + BeforeAll { + $mockStartupParameters = '-dC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\master.mdf;-eC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\Log\ERRORLOG;-lC:\Program Files\Microsoft SQL Server\MSSQL16.SQL2022\MSSQL\DATA\log.ldf;-t8688;-T3226' + $mockExpectedStartupParameters = $mockStartupParameters -replace ';-t8688' + + Mock -CommandName Assert-ElevatedUser + Mock -CommandName Get-SqlDscManagedComputerService -MockWith { + return $mockServiceObject + } + } + + BeforeEach { + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.StartupParameters = $mockStartupParameters + $mockServiceObject.Type = 'SqlServer' + + $mockServiceObject | + Add-Member -MemberType 'ScriptMethod' -Name 'Alter' -Value { + $script:mockMethodAlterCallCount += 1 + } -PassThru -Force + + $script:mockMethodAlterCallCount = 0 + } + + It 'Should call the mocked method and have correct value in the object, removed all internal trace flag ang kept normal trace flags' { + { Set-SqlDscStartupParameter -InternalTraceFlag @() -Force } | Should -Not -Throw + + # This is the object created by the mock and modified by the command. + $mockServiceObject.StartupParameters | Should -BeExactly $mockExpectedStartupParameters + + $mockMethodAlterCallCount | Should -Be 1 + } + } +} diff --git a/tests/Unit/Public/Set-SqlDscTraceFlag.Tests.ps1 b/tests/Unit/Public/Set-SqlDscTraceFlag.Tests.ps1 new file mode 100644 index 000000000..dcb6637e7 --- /dev/null +++ b/tests/Unit/Public/Set-SqlDscTraceFlag.Tests.ps1 @@ -0,0 +1,184 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 2>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:dscModuleName + + # Loading mocked classes + Add-Type -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath '../Stubs') -ChildPath 'SMO.cs') + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscModuleName -All | Remove-Module -Force + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'Set-SqlDscTraceFlag' -Tag 'Public' { + It 'Should have the correct parameters in parameter set ' -ForEach @( + @{ + MockParameterSetName = 'ByServiceObject' + MockExpectedParameters = '-ServiceObject -TraceFlag [-Force] [-WhatIf] [-Confirm] []' + } + @{ + MockParameterSetName = 'ByServerName' + MockExpectedParameters = '-TraceFlag [-ServerName ] [-InstanceName ] [-Force] [-WhatIf] [-Confirm] []' + } + ) { + $result = (Get-Command -Name 'Set-SqlDscTraceFlag').ParameterSets | + Where-Object -FilterScript { + $_.Name -eq $mockParameterSetName + } | + Select-Object -Property @( + @{ + Name = 'ParameterSetName' + Expression = { $_.Name } + }, + @{ + Name = 'ParameterListAsString' + Expression = { $_.ToString() } + } + ) + + $result.ParameterSetName | Should -Be $MockParameterSetName + $result.ParameterListAsString | Should -Be $MockExpectedParameters + } + + Context 'When passing $null as ServiceObject' { + It 'Should throw the correct error' { + $mockErrorMessage = 'Cannot bind argument to parameter ''ServiceObject'' because it is null.' + + { Set-SqlDscTraceFlag -ServiceObject $null } | Should -Throw -ExpectedMessage $mockErrorMessage + } + } + + Context 'When setting a trace flag by a service object' { + BeforeAll { + Mock -CommandName Set-SqlDscStartupParameter + + $mockServiceObject = [Microsoft.SqlServer.Management.Smo.Wmi.Service]::CreateTypeInstance() + $mockServiceObject.Name = 'MSSQL$SQL2022' + } + + Context 'When using parameter Confirm with value $false' { + It 'Should call the mocked method and have correct value in the object' { + { Set-SqlDscTraceFlag -ServiceObject $mockServiceObject -TraceFlag 4199 -Confirm:$false } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscStartupParameter -ParameterFilter { + $TraceFlag -contains 4199 + } -Exactly -Times 1 -Scope It + } + } + + Context 'When using parameter Force' { + It 'Should call the mocked method and have correct value in the object' { + { Set-SqlDscTraceFlag -ServiceObject $mockServiceObject -TraceFlag 4199 -Force } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscStartupParameter -ParameterFilter { + $TraceFlag -contains 4199 + } -Exactly -Times 1 -Scope It + } + } + + Context 'When using parameter WhatIf' { + It 'Should not call the mocked method and should not have changed the value in the object' { + { Set-SqlDscTraceFlag -ServiceObject $mockServiceObject -TraceFlag 4199 -WhatIf } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscStartupParameter -Exactly -Times 0 -Scope It + } + } + + Context 'When passing parameter ServerObject over the pipeline' { + It 'Should call the mocked method and have correct value in the object' { + { $mockServiceObject | Set-SqlDscTraceFlag -TraceFlag 4199 -Force } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscStartupParameter -ParameterFilter { + $TraceFlag -contains 4199 + } -Exactly -Times 1 -Scope It + } + } + } + + Context 'When setting a trace flag by default parameter set and parameters default values' { + BeforeAll { + Mock -CommandName Set-SqlDscStartupParameter + } + + Context 'When using parameter Confirm with value $false' { + It 'Should call the mocked method and have correct value in the object' { + { Set-SqlDscTraceFlag -TraceFlag 4199 -Confirm:$false } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscStartupParameter -ParameterFilter { + $TraceFlag -contains 4199 + } -Exactly -Times 1 -Scope It + } + } + + Context 'When using parameter Force' { + It 'Should call the mocked method and have correct value in the object' { + { Set-SqlDscTraceFlag -TraceFlag 4199 -Force } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscStartupParameter -ParameterFilter { + $TraceFlag -contains 4199 + } -Exactly -Times 1 -Scope It + } + } + + Context 'When using parameter WhatIf' { + It 'Should not call the mocked method and should not have changed the value in the object' { + { Set-SqlDscTraceFlag -TraceFlag 4199 -WhatIf } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscStartupParameter -Exactly -Times 0 -Scope It + } + } + } + + Context 'When clearing all trace flags' { + BeforeAll { + Mock -CommandName Set-SqlDscStartupParameter + } + + It 'Should call the mocked method and have correct value in the object' { + { Set-SqlDscTraceFlag -TraceFlag @() -Force } | Should -Not -Throw + + Should -Invoke -CommandName Set-SqlDscStartupParameter -ParameterFilter { + $TraceFlag.Count -eq 0 + } -Exactly -Times 1 -Scope It + } + } +} diff --git a/tests/Unit/Stubs/SMO.cs b/tests/Unit/Stubs/SMO.cs index 1f21e9cea..1ae7ad165 100644 --- a/tests/Unit/Stubs/SMO.cs +++ b/tests/Unit/Stubs/SMO.cs @@ -922,9 +922,82 @@ public Audit(Microsoft.SqlServer.Management.Smo.Server server, System.String nam public Microsoft.SqlServer.Management.Smo.SqlSmoState? State { get; set; } } + public class Property + { + // Property + public System.String Name { get; set; } + public System.Object Value { get; set; } + public System.Type Type { get; set; } + public System.Boolean Writable { get; set; } + public System.Boolean Readable { get; set; } + public System.Boolean Expensive { get; set; } + public System.Boolean Dirty { get; set; } + public System.Boolean Retrieved { get; set; } + public System.Boolean IsNull { get; set; } + + // Fabricated constructor + private Property() { } + public static Property CreateTypeInstance() + { + return new Property(); + } + } + + public class PropertyCollection + { + // Property + public System.Int32 Count { get; set; } + public Microsoft.SqlServer.Management.Smo.Property Item { get; set; } + public System.Boolean IsSynchronized { get; set; } + public System.Object SyncRoot { get; set; } + + // Fabricated constructor + private PropertyCollection() { } + public static PropertyCollection CreateTypeInstance() + { + return new PropertyCollection(); + } + } + #endregion Public Classes } +namespace Microsoft.SqlServer.Management.Sdk.Sfc +{ + public class XPathExpression + { + // Constructor + public XPathExpression(System.String strXPathExpression) { } + + // Property + public System.Int32 Length { get; set; } + public System.String ExpressionSkeleton { get; set; } + + // Fabricated constructor + private XPathExpression() { } + public static XPathExpression CreateTypeInstance() + { + return new XPathExpression(); + } + } + + public class Urn + { + // Constructor + public Urn() { } + public Urn(System.String value) { } + + // Property + public Microsoft.SqlServer.Management.Sdk.Sfc.XPathExpression XPathExpression { get; set; } + public System.String Value { get; set; } + public System.String DomainInstanceName { get; set; } + public System.String Type { get; set; } + public Microsoft.SqlServer.Management.Sdk.Sfc.Urn Parent { get; set; } + + } + +} + namespace Microsoft.SqlServer.Management.Smo.Wmi { #region Public Enums @@ -932,38 +1005,408 @@ namespace Microsoft.SqlServer.Management.Smo.Wmi // TypeName: Microsoft.SqlServer.Management.Smo.Wmi.ManagedServiceType // Used by: // DSC_SqlServiceAccount.Tests.ps1 - public enum ManagedServiceType + public enum ManagedServiceType : int { SqlServer = 1, - SqlAgent = 2, - Search = 3, - SqlServerIntegrationService = 4, - AnalysisServer = 5, - ReportServer = 6, - SqlBrowser = 7, + NotificationServer = 8, + } + + public enum ServiceErrorControl : int + { + Ignore = 0, + Normal = 1, + Severe = 2, + Critical = 3, + Unknown = 4, + } + + public enum ServiceState : int + { + Stopped = 1, + StartPending = 2, + StopPending = 3, + Running = 4, + ContinuePending = 5, + PausePending = 6, + Paused = 7, + Unknown = 8, + } - NotificationServer = 8 + public enum ServiceStartMode : int + { + Boot = 0, + System = 1, + Auto = 2, + Manual = 3, + Disabled = 4, + } + + public enum ProviderArchitecture : int + { + Default = 0, + Use32bit = 32, + Use64bit = 64, } #endregion #region Public Classes + // TypeName: Microsoft.SqlServer.Management.Smo.Wmi.Service + // Used by: + // Get-SqlDscManagedComputerService + public class Service + { + // Property + public Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer Parent { get; set; } + public System.Boolean AcceptsPause { get; set; } + public System.Boolean AcceptsStop { get; set; } + public System.String Description { get; set; } + public System.String DisplayName { get; set; } + public Microsoft.SqlServer.Management.Smo.Wmi.ServiceErrorControl ErrorControl { get; set; } + public System.Int32 ExitCode { get; set; } + public System.String PathName { get; set; } + public System.Int32 ProcessId { get; set; } + public System.String ServiceAccount { get; set; } + public Microsoft.SqlServer.Management.Smo.Wmi.ServiceState ServiceState { get; set; } + public Microsoft.SqlServer.Management.Smo.Wmi.ServiceStartMode StartMode { get; set; } + public Microsoft.SqlServer.Management.Smo.Wmi.ManagedServiceType Type { get; set; } + public System.Boolean IsHadrEnabled { get; set; } + public System.String StartupParameters { get; set; } + public System.Collections.Specialized.StringCollection Dependencies { get; set; } + public Microsoft.SqlServer.Management.Smo.PropertyCollection AdvancedProperties { get; set; } + public Microsoft.SqlServer.Management.Sdk.Sfc.Urn Urn { get; set; } + public System.String Name { get; set; } + public Microsoft.SqlServer.Management.Smo.PropertyCollection Properties { get; set; } + public System.Object UserData { get; set; } + public Microsoft.SqlServer.Management.Smo.SqlSmoState State { get; set; } + + // Fabricated constructor + private Service() { } + public static Service CreateTypeInstance() + { + return new Service(); + } + } + + // TypeName: Microsoft.SqlServer.Management.Smo.Wmi.ServiceCollection + // Used by: + // Get-SqlDscManagedComputerService + public class ServiceCollection + { + // Property + public Microsoft.SqlServer.Management.Smo.Wmi.Service Item { get; set; } + public System.Int32 Count { get; set; } + public System.Boolean IsSynchronized { get; set; } + public System.Object SyncRoot { get; set; } + + // Fabricated constructor + private ServiceCollection() { } + public static ServiceCollection CreateTypeInstance() + { + return new ServiceCollection(); + } + } + + public class WmiConnectionInfo + { + // Property + public System.TimeSpan Timeout { get; set; } + public System.String MachineName { get; set; } + public System.String Username { get; set; } + public Microsoft.SqlServer.Management.Smo.Wmi.ProviderArchitecture ProviderArchitecture { get; set; } + + // Fabricated constructor + private WmiConnectionInfo() { } + public static WmiConnectionInfo CreateTypeInstance() + { + return new WmiConnectionInfo(); + } + } + + public class NetLibInfo + { + // Property + public System.String FileName { get; set; } + public System.String Version { get; set; } + public System.DateTime Date { get; set; } + public System.Int32 Size { get; set; } + + // Fabricated constructor + private NetLibInfo() { } + public static NetLibInfo CreateTypeInstance() + { + return new NetLibInfo(); + } + } + + public class ProtocolProperty + { + // Property + public System.String Name { get; set; } + public System.Object Value { get; set; } + public System.Type Type { get; set; } + public System.Boolean Writable { get; set; } + public System.Boolean Readable { get; set; } + public System.Boolean Expensive { get; set; } + public System.Boolean Dirty { get; set; } + public System.Boolean Retrieved { get; set; } + public System.Boolean IsNull { get; set; } + + // Fabricated constructor + private ProtocolProperty() { } + public static ProtocolProperty CreateTypeInstance() + { + return new ProtocolProperty(); + } + } + + public class ProtocolPropertyCollection + { + // Property + public System.Int32 Count { get; set; } + public System.Boolean IsSynchronized { get; set; } + public System.Object SyncRoot { get; set; } + public Microsoft.SqlServer.Management.Smo.Wmi.ProtocolProperty Item { get; set; } + + // Fabricated constructor + private ProtocolPropertyCollection() { } + public static ProtocolPropertyCollection CreateTypeInstance() + { + return new ProtocolPropertyCollection(); + } + } + + public class ClientProtocol + { + // Property + public Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer Parent { get; set; } + public System.String DisplayName { get; set; } + public System.Boolean IsEnabled { get; set; } + public System.String NetworkLibrary { get; set; } + public System.Int32 Order { get; set; } + public Microsoft.SqlServer.Management.Smo.Wmi.NetLibInfo NetLibInfo { get; set; } + public Microsoft.SqlServer.Management.Smo.Wmi.ProtocolPropertyCollection ProtocolProperties { get; set; } + public Microsoft.SqlServer.Management.Sdk.Sfc.Urn Urn { get; set; } + public System.String Name { get; set; } + public Microsoft.SqlServer.Management.Smo.PropertyCollection Properties { get; set; } + public System.Object UserData { get; set; } + public Microsoft.SqlServer.Management.Smo.SqlSmoState State { get; set; } + + // Fabricated constructor + private ClientProtocol() { } + public static ClientProtocol CreateTypeInstance() + { + return new ClientProtocol(); + } + } + + public class ClientProtocolCollection + { + // Property + public Microsoft.SqlServer.Management.Smo.Wmi.ClientProtocol Item { get; set; } + public System.Int32 Count { get; set; } + public System.Boolean IsSynchronized { get; set; } + public System.Object SyncRoot { get; set; } + + // Fabricated constructor + private ClientProtocolCollection() { } + public static ClientProtocolCollection CreateTypeInstance() + { + return new ClientProtocolCollection(); + } + } + + public class IPAddressPropertyCollection + { + // Property + public System.Int32 Count { get; set; } + public System.Boolean IsSynchronized { get; set; } + public System.Object SyncRoot { get; set; } + public Microsoft.SqlServer.Management.Smo.Wmi.ProtocolProperty Item { get; set; } + + // Fabricated constructor + private IPAddressPropertyCollection() { } + public static IPAddressPropertyCollection CreateTypeInstance() + { + return new IPAddressPropertyCollection(); + } + } + + public class ServerIPAddress + { + // Property + public Microsoft.SqlServer.Management.Smo.Wmi.ServerProtocol Parent { get; set; } + public Microsoft.SqlServer.Management.Smo.Wmi.IPAddressPropertyCollection IPAddressProperties { get; set; } + public System.Net.IPAddress IPAddress { get; set; } + public Microsoft.SqlServer.Management.Sdk.Sfc.Urn Urn { get; set; } + public System.String Name { get; set; } + public Microsoft.SqlServer.Management.Smo.PropertyCollection Properties { get; set; } + public System.Object UserData { get; set; } + public Microsoft.SqlServer.Management.Smo.SqlSmoState State { get; set; } + + // Fabricated constructor + private ServerIPAddress() { } + public static ServerIPAddress CreateTypeInstance() + { + return new ServerIPAddress(); + } + } + + public class ServerIPAddressCollection + { + // Property + public Microsoft.SqlServer.Management.Smo.Wmi.ServerIPAddress Item { get; set; } + public System.Int32 Count { get; set; } + public System.Boolean IsSynchronized { get; set; } + public System.Object SyncRoot { get; set; } + + // Fabricated constructor + private ServerIPAddressCollection() { } + public static ServerIPAddressCollection CreateTypeInstance() + { + return new ServerIPAddressCollection(); + } + } + + public class ServerProtocol + { + // Property + public Microsoft.SqlServer.Management.Smo.Wmi.ServerInstance Parent { get; set; } + public System.String DisplayName { get; set; } + public System.Boolean HasMultiIPAddresses { get; set; } + public System.Boolean IsEnabled { get; set; } + public Microsoft.SqlServer.Management.Smo.Wmi.ServerIPAddressCollection IPAddresses { get; set; } + public Microsoft.SqlServer.Management.Smo.Wmi.ProtocolPropertyCollection ProtocolProperties { get; set; } + public Microsoft.SqlServer.Management.Sdk.Sfc.Urn Urn { get; set; } + public System.String Name { get; set; } + public Microsoft.SqlServer.Management.Smo.PropertyCollection Properties { get; set; } + public System.Object UserData { get; set; } + public Microsoft.SqlServer.Management.Smo.SqlSmoState State { get; set; } + + // Fabricated constructor + private ServerProtocol() { } + public static ServerProtocol CreateTypeInstance() + { + return new ServerProtocol(); + } + } + + public class ServerProtocolCollection + { + // Property + public Microsoft.SqlServer.Management.Smo.Wmi.ServerProtocol Item { get; set; } + public System.Int32 Count { get; set; } + public System.Boolean IsSynchronized { get; set; } + public System.Object SyncRoot { get; set; } + + // Fabricated constructor + private ServerProtocolCollection() { } + public static ServerProtocolCollection CreateTypeInstance() + { + return new ServerProtocolCollection(); + } + } + + public class ServerInstance + { + // Property + public Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer Parent { get; set; } + public Microsoft.SqlServer.Management.Smo.Wmi.ServerProtocolCollection ServerProtocols { get; set; } + public Microsoft.SqlServer.Management.Sdk.Sfc.Urn Urn { get; set; } + public System.String Name { get; set; } + public Microsoft.SqlServer.Management.Smo.PropertyCollection Properties { get; set; } + public System.Object UserData { get; set; } + public Microsoft.SqlServer.Management.Smo.SqlSmoState State { get; set; } + + // Fabricated constructor + private ServerInstance() { } + public static ServerInstance CreateTypeInstance() + { + return new ServerInstance(); + } + } + + public class ServerInstanceCollection + { + // Property + public Microsoft.SqlServer.Management.Smo.Wmi.ServerInstance Item { get; set; } + public System.Int32 Count { get; set; } + public System.Boolean IsSynchronized { get; set; } + public System.Object SyncRoot { get; set; } + + // Fabricated constructor + private ServerInstanceCollection() { } + public static ServerInstanceCollection CreateTypeInstance() + { + return new ServerInstanceCollection(); + } + } + + public class ServerAlias + { + // Constructor + public ServerAlias(Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer managedComputer, System.String name) { } + public ServerAlias() { } + + // Property + public Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer Parent { get; set; } + public System.String ConnectionString { get; set; } + public System.String ProtocolName { get; set; } + public System.String ServerName { get; set; } + public Microsoft.SqlServer.Management.Sdk.Sfc.Urn Urn { get; set; } + public System.String Name { get; set; } + public Microsoft.SqlServer.Management.Smo.PropertyCollection Properties { get; set; } + public System.Object UserData { get; set; } + public Microsoft.SqlServer.Management.Smo.SqlSmoState State { get; set; } + } + + public class ServerAliasCollection + { + // Property + public Microsoft.SqlServer.Management.Smo.Wmi.ServerAlias Item { get; set; } + public System.Int32 Count { get; set; } + public System.Boolean IsSynchronized { get; set; } + public System.Object SyncRoot { get; set; } + + // Fabricated constructor + private ServerAliasCollection() { } + public static ServerAliasCollection CreateTypeInstance() + { + return new ServerAliasCollection(); + } + } + // TypeName: Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer // Used by: // DSC_SqlTraceFlag.Tests.ps1 + // Get-SqlDscManagedComputerService public class ManagedComputer { - public string Name; - public string State; - public ArrayList ServerInstances; - public ArrayList Services; + // Constructor + public ManagedComputer() { } + public ManagedComputer(System.String machineName) { } + public ManagedComputer(System.String machineName, System.String userName, System.String password) { } + public ManagedComputer(System.String machineName, System.String userName, System.String password, Microsoft.SqlServer.Management.Smo.Wmi.ProviderArchitecture providerArchitecture) { } + + // Property + public Microsoft.SqlServer.Management.Smo.Wmi.WmiConnectionInfo ConnectionSettings { get; set; } + public Microsoft.SqlServer.Management.Smo.Wmi.ServiceCollection Services { get; set; } + public Microsoft.SqlServer.Management.Smo.Wmi.ClientProtocolCollection ClientProtocols { get; set; } + public Microsoft.SqlServer.Management.Smo.Wmi.ServerInstanceCollection ServerInstances { get; set; } + public Microsoft.SqlServer.Management.Smo.Wmi.ServerAliasCollection ServerAliases { get; set; } + public Microsoft.SqlServer.Management.Sdk.Sfc.Urn Urn { get; set; } + public System.String Name { get; set; } + public Microsoft.SqlServer.Management.Smo.PropertyCollection Properties { get; set; } + public System.Object UserData { get; set; } + public Microsoft.SqlServer.Management.Smo.SqlSmoState State { get; set; } } + #endregion }