diff --git a/CHANGELOG.md b/CHANGELOG.md index b2b084fbd..e50bdedb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 resource README.md, and some was added to the schema MOF parameter descriptions ([issue #1580](https://github.com/dsccommunity/SqlServerDsc/issues/1580)). +### Added + +- SqlScript + - Added the DisableVariables parameter ([issue #1422](https://github.com/dsccommunity/SqlServerDsc/issues/1422)). +- SqlScriptQuery + - Added the DisableVariables parameter ([issue #1422](https://github.com/dsccommunity/SqlServerDsc/issues/1422)). + ## [14.0.0] - 2020-06-12 ### Remove diff --git a/source/DSCResources/DSC_SqlScript/DSC_SqlScript.psm1 b/source/DSCResources/DSC_SqlScript/DSC_SqlScript.psm1 index 4a7bdb010..95ca0d7ab 100644 --- a/source/DSCResources/DSC_SqlScript/DSC_SqlScript.psm1 +++ b/source/DSCResources/DSC_SqlScript/DSC_SqlScript.psm1 @@ -40,6 +40,10 @@ $script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US' Use a Windows PowerShell array to specify multiple variables and their values. For more information how to use this, please go to the help documentation for [Invoke-Sqlcmd](https://technet.microsoft.com/en-us/library/mt683370.aspx). + .PARAMETER DisableVariables + Specifies, as a boolean, whether or not PowerShell will ignore sqlcmd scripting variables that share a format such as $(variable_name). + For more information how to use this, please go to the help documentation for [Invoke-Sqlcmd](https://technet.microsoft.com/en-us/library/mt683370.aspx)")] + .PARAMETER QueryTimeout Specifies, as an integer, the number of seconds after which the T-SQL script execution will time out. In some SQL Server versions there is a bug in Invoke-Sqlcmd where the normal default value 0 (no timeout) is not respected and the default value is incorrectly set to 30 seconds. @@ -85,19 +89,24 @@ function Get-TargetResource [Parameter()] [System.String[]] - $Variable + $Variable, + + [Parameter()] + [System.Boolean] + $DisableVariables ) $serverInstance = ConvertTo-ServerInstanceName -InstanceName $InstanceName -ServerName $ServerName $invokeParameters = @{ - ServerInstance = $serverInstance - InputFile = $GetFilePath - Credential = $Credential - Variable = $Variable - QueryTimeout = $QueryTimeout - Verbose = $VerbosePreference - ErrorAction = 'Stop' + ServerInstance = $serverInstance + InputFile = $GetFilePath + Credential = $Credential + Variable = $Variable + DisableVariables = $DisableVariables + QueryTimeout = $QueryTimeout + Verbose = $VerbosePreference + ErrorAction = 'Stop' } Write-Verbose -Message ( @@ -109,15 +118,16 @@ function Get-TargetResource $getResult = Out-String -InputObject $result $returnValue = @{ - ServerName = [System.String] $ServerName - InstanceName = [System.String] $InstanceName - SetFilePath = [System.String] $SetFilePath - GetFilePath = [System.String] $GetFilePath - TestFilePath = [System.String] $TestFilePath - Credential = [System.Object] $Credential - QueryTimeout = [System.UInt32] $QueryTimeout - Variable = [System.String[]] $Variable - GetResult = [System.String[]] $getResult + ServerName = [System.String] $ServerName + InstanceName = [System.String] $InstanceName + SetFilePath = [System.String] $SetFilePath + GetFilePath = [System.String] $GetFilePath + TestFilePath = [System.String] $TestFilePath + Credential = [System.Object] $Credential + QueryTimeout = [System.UInt32] $QueryTimeout + Variable = [System.String[]] $Variable + DisableVariables = [System.Boolean] $DisableVariables + GetResult = [System.String[]] $getResult } return $returnValue @@ -164,6 +174,10 @@ function Get-TargetResource Specifies, as a string array, a Invoke-Sqlcmd scripting variable for use in the Invoke-Sqlcmd script, and sets a value for the variable. Use a Windows PowerShell array to specify multiple variables and their values. For more information how to use this, please go to the help documentation for [Invoke-Sqlcmd](https://technet.microsoft.com/en-us/library/mt683370.aspx). + + .PARAMETER DisableVariables + Specifies, as a boolean, whether or not PowerShell will ignore sqlcmd scripting variables that share a format such as $(variable_name). + For more information how to use this, please go to the help documentation for [Invoke-Sqlcmd](https://technet.microsoft.com/en-us/library/mt683370.aspx)")] #> function Set-TargetResource { @@ -202,7 +216,11 @@ function Set-TargetResource [Parameter()] [System.String[]] - $Variable + $Variable, + + [Parameter()] + [System.Boolean] + $DisableVariables ) $serverInstance = ConvertTo-ServerInstanceName -InstanceName $InstanceName -ServerName $ServerName @@ -212,13 +230,14 @@ function Set-TargetResource ) $invokeParameters = @{ - ServerInstance = $serverInstance - InputFile = $SetFilePath - Credential = $Credential - Variable = $Variable - QueryTimeout = $QueryTimeout - Verbose = $VerbosePreference - ErrorAction = 'Stop' + ServerInstance = $serverInstance + InputFile = $SetFilePath + Credential = $Credential + Variable = $Variable + DisableVariables = $DisableVariables + QueryTimeout = $QueryTimeout + Verbose = $VerbosePreference + ErrorAction = 'Stop' } Invoke-SqlScript @invokeParameters @@ -266,6 +285,9 @@ function Set-TargetResource Use a Windows PowerShell array to specify multiple variables and their values. For more information how to use this, please go to the help documentation for [Invoke-Sqlcmd](https://technet.microsoft.com/en-us/library/mt683370.aspx). + .PARAMETER DisableVariables + Specifies, as a boolean, whether or not PowerShell will ignore sqlcmd scripting variables that share a format such as $(variable_name). + For more information how to use this, please go to the help documentation for [Invoke-Sqlcmd](https://technet.microsoft.com/en-us/library/mt683370.aspx). #> function Test-TargetResource { @@ -305,7 +327,11 @@ function Test-TargetResource [Parameter()] [System.String[]] - $Variable + $Variable, + + [Parameter()] + [System.Boolean] + $DisableVariables ) Write-Verbose -Message ( @@ -315,13 +341,14 @@ function Test-TargetResource $serverInstance = ConvertTo-ServerInstanceName -InstanceName $InstanceName -ServerName $ServerName $invokeParameters = @{ - ServerInstance = $serverInstance - InputFile = $TestFilePath - Credential = $Credential - Variable = $Variable - QueryTimeout = $QueryTimeout - Verbose = $VerbosePreference - ErrorAction = 'Stop' + ServerInstance = $serverInstance + InputFile = $TestFilePath + Credential = $Credential + Variable = $Variable + DisableVariables = $DisableVariables + QueryTimeout = $QueryTimeout + Verbose = $VerbosePreference + ErrorAction = 'Stop' } $result = $null diff --git a/source/DSCResources/DSC_SqlScript/DSC_SqlScript.schema.mof b/source/DSCResources/DSC_SqlScript/DSC_SqlScript.schema.mof index 2c23441d3..675f32a81 100644 --- a/source/DSCResources/DSC_SqlScript/DSC_SqlScript.schema.mof +++ b/source/DSCResources/DSC_SqlScript/DSC_SqlScript.schema.mof @@ -8,6 +8,7 @@ class DSC_SqlScript : OMI_BaseResource [Write, Description("Specifies the host name of the SQL Server to be configured. Default value is $env:COMPUTERNAME.")] String ServerName; [Write, EmbeddedInstance("MSFT_Credential"), Description("The credentials to authenticate with, using SQL Authentication. To authenticate using Windows Authentication assign the credentials to the built-in parameter 'PsDscRunAsCredential'. If neither of the parameters 'Credential' and 'PsDscRunAsCredential' are assigned, then the SYSTEM account will be used to authenticate using Windows Authentication.")] String Credential; [Write, Description("Specifies, as a string array, a scripting variable for use in the sql script, and sets a value for the variable. Use an array to specify multiple variables and their values. For more information how to use this, please go to the help documentation for [Invoke-Sqlcmd](https://technet.microsoft.com/en-us/library/mt683370.aspx)")] String Variable[]; + [Write, Description("Specifies, as a boolean, whether or not PowerShell will ignore sqlcmd scripting variables that share a format such as $(variable_name). For more information how to use this, please go to the help documentation for [Invoke-Sqlcmd](https://technet.microsoft.com/en-us/library/mt683370.aspx)")] Boolean DisableVariables; [Write, Description("Specifies, as an integer, the number of seconds after which the T-SQL script execution will time out. In some SQL Server versions there is a bug in Invoke-Sqlcmd where the normal default value 0 (no timeout) is not respected and the default value is incorrectly set to 30 seconds.")] UInt32 QueryTimeout; [Read, Description("Returns the result from the T-SQL script provided in the parameter 'GetFilePath' when cmdlet Get-DscConfiguration is run.")] String GetResult[]; }; diff --git a/source/DSCResources/DSC_SqlScriptQuery/DSC_SqlScriptQuery.psm1 b/source/DSCResources/DSC_SqlScriptQuery/DSC_SqlScriptQuery.psm1 index c40388a74..2d6f90abb 100644 --- a/source/DSCResources/DSC_SqlScriptQuery/DSC_SqlScriptQuery.psm1 +++ b/source/DSCResources/DSC_SqlScriptQuery/DSC_SqlScriptQuery.psm1 @@ -40,6 +40,10 @@ $script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US' Use a Windows PowerShell array to specify multiple variables and their values. For more information how to use this, please go to the help documentation for [Invoke-Sqlcmd](https://technet.microsoft.com/en-us/library/mt683370.aspx). + .PARAMETER DisableVariables + Specifies, as a boolean, whether or not PowerShell will ignore sqlcmd scripting variables that share a format such as $(variable_name). + For more information how to use this, please go to the help documentation for [Invoke-Sqlcmd](https://technet.microsoft.com/en-us/library/mt683370.aspx). + .PARAMETER QueryTimeout Specifies, as an integer, the number of seconds after which the T-SQL script execution will time out. In some SQL Server versions there is a bug in Invoke-Sqlcmd where the normal default value 0 (no timeout) is not respected and the default value is incorrectly set to 30 seconds. @@ -85,7 +89,11 @@ function Get-TargetResource [Parameter()] [System.String[]] - $Variable + $Variable, + + [Parameter()] + [System.Boolean] + $DisableVariables ) Write-Verbose -Message ( @@ -95,13 +103,14 @@ function Get-TargetResource $serverInstance = ConvertTo-ServerInstanceName -InstanceName $InstanceName -ServerName $ServerName $invokeParameters = @{ - Query = $GetQuery - ServerInstance = $serverInstance - Credential = $Credential - Variable = $Variable - QueryTimeout = $QueryTimeout - Verbose = $VerbosePreference - ErrorAction = 'Stop' + Query = $GetQuery + ServerInstance = $serverInstance + Credential = $Credential + Variable = $Variable + DisableVariables = $DisableVariables + QueryTimeout = $QueryTimeout + Verbose = $VerbosePreference + ErrorAction = 'Stop' } $result = Invoke-SqlScript @invokeParameters @@ -109,15 +118,16 @@ function Get-TargetResource $getResult = Out-String -InputObject $result $returnValue = @{ - ServerName = [System.String] $ServerName - InstanceName = [System.String] $InstanceName - GetQuery = [System.String] $GetQuery - TestQuery = [System.String] $TestQuery - SetQuery = [System.String] $SetQuery - Credential = [System.Object] $Credential - QueryTimeout = [System.UInt32] $QueryTimeout - Variable = [System.String[]] $Variable - GetResult = [System.String[]] $getResult + ServerName = [System.String] $ServerName + InstanceName = [System.String] $InstanceName + GetQuery = [System.String] $GetQuery + TestQuery = [System.String] $TestQuery + SetQuery = [System.String] $SetQuery + Credential = [System.Object] $Credential + QueryTimeout = [System.UInt32] $QueryTimeout + Variable = [System.String[]] $Variable + DisableVariables = [System.Boolean] $DisableVariables + GetResult = [System.String[]] $getResult } return $returnValue @@ -164,6 +174,10 @@ function Get-TargetResource Specifies, as a string array, a Invoke-Sqlcmd scripting variable for use in the Invoke-Sqlcmd script, and sets a value for the variable. Use a Windows PowerShell array to specify multiple variables and their values. For more information how to use this, please go to the help documentation for [Invoke-Sqlcmd](https://technet.microsoft.com/en-us/library/mt683370.aspx). + + .PARAMETER DisableVariables + Specifies, as a boolean, whether or not PowerShell will ignore sqlcmd scripting variables that share a format such as $(variable_name). + For more information how to use this, please go to the help documentation for [Invoke-Sqlcmd](https://technet.microsoft.com/en-us/library/mt683370.aspx)")] #> function Set-TargetResource { @@ -202,7 +216,11 @@ function Set-TargetResource [Parameter()] [System.String[]] - $Variable + $Variable, + + [Parameter()] + [System.Boolean] + $DisableVariables ) Write-Verbose -Message ( @@ -212,13 +230,14 @@ function Set-TargetResource $serverInstance = ConvertTo-ServerInstanceName -InstanceName $InstanceName -ServerName $ServerName $invokeParameters = @{ - Query = $SetQuery - ServerInstance = $serverInstance - Credential = $Credential - Variable = $Variable - QueryTimeout = $QueryTimeout - Verbose = $VerbosePreference - ErrorAction = 'Stop' + Query = $SetQuery + ServerInstance = $serverInstance + Credential = $Credential + Variable = $Variable + DisableVariables = $DisableVariables + QueryTimeout = $QueryTimeout + Verbose = $VerbosePreference + ErrorAction = 'Stop' } Invoke-SqlScript @invokeParameters @@ -266,6 +285,10 @@ function Set-TargetResource Use a Windows PowerShell array to specify multiple variables and their values. For more information how to use this, please go to the help documentation for [Invoke-Sqlcmd](https://technet.microsoft.com/en-us/library/mt683370.aspx). + .PARAMETER DisableVariables + Specifies, as a boolean, whether or not PowerShell will ignore sqlcmd scripting variables that share a format such as $(variable_name). + For more information how to use this, please go to the help documentation for [Invoke-Sqlcmd](https://technet.microsoft.com/en-us/library/mt683370.aspx)")] + #> function Test-TargetResource { @@ -305,7 +328,11 @@ function Test-TargetResource [Parameter()] [System.String[]] - $Variable + $Variable, + + [Parameter()] + [System.Boolean] + $DisableVariables ) Write-Verbose -Message ( @@ -315,13 +342,14 @@ function Test-TargetResource $serverInstance = ConvertTo-ServerInstanceName -InstanceName $InstanceName -ServerName $ServerName $invokeParameters = @{ - Query = $TestQuery - ServerInstance = $serverInstance - Credential = $Credential - Variable = $Variable - QueryTimeout = $QueryTimeout - Verbose = $VerbosePreference - ErrorAction = 'Stop' + Query = $TestQuery + ServerInstance = $serverInstance + Credential = $Credential + Variable = $Variable + DisableVariables = $DisableVariables + QueryTimeout = $QueryTimeout + Verbose = $VerbosePreference + ErrorAction = 'Stop' } $result = $null diff --git a/source/DSCResources/DSC_SqlScriptQuery/DSC_SqlScriptQuery.schema.mof b/source/DSCResources/DSC_SqlScriptQuery/DSC_SqlScriptQuery.schema.mof index 6b7e02628..a450449c4 100644 --- a/source/DSCResources/DSC_SqlScriptQuery/DSC_SqlScriptQuery.schema.mof +++ b/source/DSCResources/DSC_SqlScriptQuery/DSC_SqlScriptQuery.schema.mof @@ -8,6 +8,7 @@ class DSC_SqlScriptQuery : OMI_BaseResource [Write, Description("Specifies the host name of the SQL Server to be configured. Default value is $env:COMPUTERNAME.")] String ServerName; [Write, EmbeddedInstance("MSFT_Credential"), Description("The credentials to authenticate with, using SQL Authentication. To authenticate using Windows Authentication, assign the credentials to the built-in parameter 'PsDscRunAsCredential'. If neither of the parameters 'Credential' and 'PsDscRunAsCredential' are assigned then the SYSTEM account will be used to authenticate using Windows Authentication.")] String Credential; [Write, Description("Specifies, as a string array, a scripting variable for use in the sql script, and sets a value for the variable. Use a Windows PowerShell array to specify multiple variables and their values. For more information how to use this, please go to the help documentation for [Invoke-Sqlcmd](https://technet.microsoft.com/en-us/library/mt683370.aspx)")] String Variable[]; + [Write, Description("Specifies, as a boolean, whether or not PowerShell will ignore sqlcmd scripting variables that share a format such as $(variable_name). For more information how to use this, please go to the help documentation for [Invoke-Sqlcmd](https://technet.microsoft.com/en-us/library/mt683370.aspx)")] Boolean DisableVariables; [Write, Description("Specifies, as an integer, the number of seconds after which the T-SQL script execution will time out. In some SQL Server versions there is a bug in Invoke-Sqlcmd where the normal default value 0 (no timeout) is not respected and the default value is incorrectly set to 30 seconds.")] UInt32 QueryTimeout; [Read, Description("Returns the result from the T-SQL script provided in the parameter 'GetQuery' when cmdlet Get-DscConfiguration is run.")] String GetResult[]; }; diff --git a/source/Examples/Resources/SqlScript/4-RunScriptUsingDisabledVariables.ps1 b/source/Examples/Resources/SqlScript/4-RunScriptUsingDisabledVariables.ps1 new file mode 100644 index 000000000..9e672c731 --- /dev/null +++ b/source/Examples/Resources/SqlScript/4-RunScriptUsingDisabledVariables.ps1 @@ -0,0 +1,31 @@ +<# + .DESCRIPTION + This example shows how to run SQL script with disabled variables. +#> + +Configuration Example +{ + param + ( + [Parameter(Mandatory = $true)] + [System.Management.Automation.PSCredential] + $SqlCredential + ) + + Import-DscResource -ModuleName 'SqlServerDsc' + + Node localhost + { + SqlScript 'RunWithDisabledVariables' + { + ServerName = 'localhost' + InstanceName = 'SQL2016' + Credential = $SqlCredential + + SetFilePath = 'C:\DSCTemp\SQLScripts\Set-RunSQLScript.sql' + TestFilePath = 'C:\DSCTemp\SQLScripts\Test-RunSQLScript.sql' + GetFilePath = 'C:\DSCTemp\SQLScripts\Get-RunSQLScript.sql' + DisableVariables = $true + } + } +} diff --git a/source/Examples/Resources/SqlScriptQuery/4-RunScriptUsingDisabledVariables.ps1 b/source/Examples/Resources/SqlScriptQuery/4-RunScriptUsingDisabledVariables.ps1 new file mode 100644 index 000000000..535248d62 --- /dev/null +++ b/source/Examples/Resources/SqlScriptQuery/4-RunScriptUsingDisabledVariables.ps1 @@ -0,0 +1,31 @@ +<# + .DESCRIPTION + This example shows how to run SQL script using disabled variables. +#> + +Configuration Example +{ + param + ( + [Parameter(Mandatory = $true)] + [System.Management.Automation.PSCredential] + $SqlCredential + ) + + Import-DscResource -ModuleName 'SqlServerDsc' + + Node localhost + { + SqlScriptQuery 'RunWithDisabledVariables' + { + ServerName = 'localhost' + InstanceName = 'SQL2016' + Credential = $SqlCredential + + SetQuery = 'Set query' + TestQuery = 'Test query' + GetQuery = 'Get query' + DisableVariables = $true + } + } +} diff --git a/source/Modules/SqlServerDsc.Common/SqlServerDsc.Common.psm1 b/source/Modules/SqlServerDsc.Common/SqlServerDsc.Common.psm1 index 51ad8d1a5..79007e021 100644 --- a/source/Modules/SqlServerDsc.Common/SqlServerDsc.Common.psm1 +++ b/source/Modules/SqlServerDsc.Common/SqlServerDsc.Common.psm1 @@ -2045,6 +2045,10 @@ function Test-ActiveNode .PARAMETER Variable Creates a Invoke-Sqlcmd scripting variable for use in the Invoke-Sqlcmd script, and sets a value for the variable. + + .PARAMETER DisableVariables + Specifies, as a boolean, whether or not PowerShell will ignore sqlcmd scripting variables that share a format such as $(variable_name). + For more information how to use this, please go to the help documentation for [Invoke-Sqlcmd](https://technet.microsoft.com/en-us/library/mt683370.aspx)")] #> function Invoke-SqlScript { @@ -2074,7 +2078,11 @@ function Invoke-SqlScript [Parameter()] [System.String[]] - $Variable + $Variable, + + [Parameter()] + [System.Boolean] + $DisableVariables ) Import-SQLPSModule diff --git a/tests/Integration/DSC_SqlScript.Integration.Tests.ps1 b/tests/Integration/DSC_SqlScript.Integration.Tests.ps1 index 460dc2bcf..348b9e537 100644 --- a/tests/Integration/DSC_SqlScript.Integration.Tests.ps1 +++ b/tests/Integration/DSC_SqlScript.Integration.Tests.ps1 @@ -205,6 +205,120 @@ try Test-DscConfiguration -Verbose | Should -Be 'True' } } + + $configurationName = "$($script:dscResourceName)_RunSqlScriptWithVariablesDisabled_Config" + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + $configurationParameters = @{ + OutputPath = $TestDrive + # The variable $ConfigurationData was dot-sourced above. + ConfigurationData = $ConfigurationData + } + + & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + Start-DscConfiguration @startDscConfigurationParameters + } | Should -Not -Throw + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + { + $script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction Stop + } | Should -Not -Throw + } + + It 'Should have set the resource and all the parameters should match' { + $resourceCurrentState = $script:currentConfiguration | Where-Object -FilterScript { + $_.ConfigurationName -eq $configurationName ` + -and $_.ResourceId -eq $resourceId + } + + <# + This returns an array of string containing the result of the + get scripts JSON output. The output looks like the below. + + ``` + JSON_F52E2B61-18A1-11d1-B105-00805F49916B + ----------------------------------------- + [{"Name":"ScriptDatabase1"}] + ``` + + This could have been easier by just having this test + $resourceCurrentState.GetResult | Should -Match 'ScriptDatabase1' + but for making sure the returned data is actually usable, this + parses the returned data to an object. + #> + $regularExpression = [regex] '\[.*\]' + if ($regularExpression.IsMatch($resourceCurrentState.GetResult)) + { + $regularExpressionMatch = $regularExpression.Match($resourceCurrentState.GetResult).Value + } + else + { + Write-Verbose -Message ('Unexpected output from Get-TargetResource: {0}' -f $resourceCurrentState.GetResult) -Verbose + $regularExpressionMatch = '[{"Name":""}]' + } + + try + { + $resultObject = $regularExpressionMatch | ConvertFrom-Json + } + catch + { + Write-Verbose -Message ('Output from Get-TargetResource: {0}' -f $resourceCurrentState.GetResult) -Verbose + Write-Verbose -Message ('Result from regular expression match: {0}' -f $regularExpressionMatch) -Verbose + throw $_ + } + + $resultObject.Name | Should -Be $ConfigurationData.AllNodes.Database3Name + + $resourceCurrentState.ServerName | Should -Be $ConfigurationData.AllNodes.ServerName + $resourceCurrentState.InstanceName | Should -Be $ConfigurationData.AllNodes.InstanceName + $resourceCurrentState.GetFilePath | Should -Be $ConfigurationData.AllNodes.GetSqlScriptPath + $resourceCurrentState.TestFilePath | Should -Be $ConfigurationData.AllNodes.TestSqlScriptPath + $resourceCurrentState.SetFilePath | Should -Be $ConfigurationData.AllNodes.SetSqlScriptPath + } + + It 'Should return $true when Test-DscConfiguration is run' { + Test-DscConfiguration -Verbose | Should -Be 'True' + } + } + + $configurationName = "$($script:dscResourceName)_RemoveDatabase3_Config" + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + $configurationParameters = @{ + OutputPath = $TestDrive + # The variable $ConfigurationData was dot-sourced above. + ConfigurationData = $ConfigurationData + } + + & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + Start-DscConfiguration @startDscConfigurationParameters + } | Should -Not -Throw + } + } } } finally diff --git a/tests/Integration/DSC_SqlScript.config.ps1 b/tests/Integration/DSC_SqlScript.config.ps1 index f530111c2..47031f504 100644 --- a/tests/Integration/DSC_SqlScript.config.ps1 +++ b/tests/Integration/DSC_SqlScript.config.ps1 @@ -28,6 +28,7 @@ else Database1Name = 'ScriptDatabase1' Database2Name = 'ScriptDatabase2' + Database3Name = '$(DatabaseName)' GetSqlScriptPath = Join-Path -Path $env:SystemDrive -ChildPath ([System.IO.Path]::GetRandomFileName()) SetSqlScriptPath = Join-Path -Path $env:SystemDrive -ChildPath ([System.IO.Path]::GetRandomFileName()) @@ -254,3 +255,65 @@ Configuration DSC_SqlScript_RunSqlScriptAsSqlUser_Config } } } + +<# + .SYNOPSIS + Runs the SQL script with variables disabled. + + .NOTES + When the test is run with the DisableVariables parameter the ConfigData variable as it apears in the query will be used as the database name. + For example if the ConfigData database name is written as $(DatabaseName) in the T-SQL then the name of the database created will be $(DatabaseName). + It might appear odd but it is a valid name. +#> +Configuration DSC_SqlScript_RunSqlScriptWithVariablesDisabled_Config +{ + Import-DscResource -ModuleName 'SqlServerDsc' + + node $AllNodes.NodeName + { + SqlScript 'Integration_Test' + { + ServerName = $Node.ServerName + InstanceName = $Node.InstanceName + + GetFilePath = $Node.GetSqlScriptPath + TestFilePath = $Node.TestSqlScriptPath + SetFilePath = $Node.SetSqlScriptPath + DisableVariables = $true + QueryTimeout = 30 + Credential = New-Object ` + -TypeName System.Management.Automation.PSCredential ` + -ArgumentList @($Node.SqlLogin_UserName, (ConvertTo-SecureString -String $Node.SqlLogin_Password -AsPlainText -Force)) + } + } +} + +<# + .SYNOPSIS + Remove the database created from the DisabledVariables test. + + .NOTES + The current integration test run order has SqlScriptQuery running after SqlScript. Since both the SqlScript and SqlScriptQuery + resources use the same database name variable in their ConfigData queries it is imperative this database is absent when + the SqlScriptQuery resource runs its DisableVariables integration test. +#> +Configuration DSC_SqlScript_RemoveDatabase3_Config +{ + Import-DscResource -ModuleName 'SqlServerDsc' + + node $AllNodes.NodeName + { + SqlDatabase 'RemoveDatabase3' + { + Ensure = 'Absent' + ServerName = $Node.ServerName + InstanceName = $Node.InstanceName + Name = $Node.Database3Name + + PsDscRunAsCredential = New-Object ` + -TypeName System.Management.Automation.PSCredential ` + -ArgumentList @($Node.Admin_UserName, (ConvertTo-SecureString -String $Node.Admin_Password -AsPlainText -Force)) + } + } +} + diff --git a/tests/Integration/DSC_SqlScriptQuery.Integration.Tests.ps1 b/tests/Integration/DSC_SqlScriptQuery.Integration.Tests.ps1 index 7a913d8f2..61fbd3993 100644 --- a/tests/Integration/DSC_SqlScriptQuery.Integration.Tests.ps1 +++ b/tests/Integration/DSC_SqlScriptQuery.Integration.Tests.ps1 @@ -173,6 +173,121 @@ try Test-DscConfiguration -Verbose | Should -Be 'True' } } + + $configurationName = "$($script:dscResourceName)_RunSqlScriptQueryWithVariablesDisabled_Config" + + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + $configurationParameters = @{ + OutputPath = $TestDrive + # The variable $ConfigurationData was dot-sourced above. + ConfigurationData = $ConfigurationData + } + + & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + Start-DscConfiguration @startDscConfigurationParameters + } | Should -Not -Throw + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + { + $script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction Stop + } | Should -Not -Throw + } + + It 'Should have set the resource and all the parameters should match' { + $resourceCurrentState = $script:currentConfiguration | Where-Object -FilterScript { + $_.ConfigurationName -eq $configurationName ` + -and $_.ResourceId -eq $resourceId + } + + <# + This returns an array of string containing the result of the + get scripts JSON output. The output looks like the below. + + ``` + JSON_F52E2B61-18A1-11d1-B105-00805F49916B + ----------------------------------------- + [{"Name":"ScriptDatabase1"}] + ``` + + This could have been easier by just having this test + $resourceCurrentState.GetResult | Should -Match 'ScriptDatabase1' + but for making sure the returned data is actually usable, this + parses the returned data to an object. + #> + $regularExpression = [regex] '\[.*\]' + if ($regularExpression.IsMatch($resourceCurrentState.GetResult)) + { + $regularExpressionMatch = $regularExpression.Match($resourceCurrentState.GetResult).Value + } + else + { + Write-Verbose -Message ('Unexpected output from Get-TargetResource: {0}' -f $resourceCurrentState.GetResult) -Verbose + $regularExpressionMatch = '[{"Name":""}]' + } + + try + { + $resultObject = $regularExpressionMatch | ConvertFrom-Json + } + catch + { + Write-Verbose -Message ('Output from Get-TargetResource: {0}' -f $resourceCurrentState.GetResult) -Verbose + Write-Verbose -Message ('Result from regular expression match: {0}' -f $regularExpressionMatch) -Verbose + throw $_ + } + + $resultObject.Name | Should -Be $ConfigurationData.AllNodes.Database3Name + + $resourceCurrentState.ServerName | Should -Be $ConfigurationData.AllNodes.ServerName + $resourceCurrentState.InstanceName | Should -Be $ConfigurationData.AllNodes.InstanceName + $resourceCurrentState.GetQuery -replace '\r\n', "`n" | Should -Be ($ConfigurationData.AllNodes.GetQuery -replace '\r\n', "`n") + $resourceCurrentState.TestQuery -replace '\r\n', "`n" | Should -Be ($ConfigurationData.AllNodes.TestQuery -replace '\r\n', "`n") + $resourceCurrentState.SetQuery -replace '\r\n', "`n" | Should -Be ($ConfigurationData.AllNodes.SetQuery -replace '\r\n', "`n") + } + + It 'Should return $true when Test-DscConfiguration is run' { + Test-DscConfiguration -Verbose | Should -Be 'True' + } + } + + $configurationName = "$($script:dscResourceName)_RemoveDatabase3_Config" + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + $configurationParameters = @{ + OutputPath = $TestDrive + # The variable $ConfigurationData was dot-sourced above. + ConfigurationData = $ConfigurationData + } + + & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + Start-DscConfiguration @startDscConfigurationParameters + } | Should -Not -Throw + } + } } } finally diff --git a/tests/Integration/DSC_SqlScriptQuery.config.ps1 b/tests/Integration/DSC_SqlScriptQuery.config.ps1 index 59635239c..93c50f693 100644 --- a/tests/Integration/DSC_SqlScriptQuery.config.ps1 +++ b/tests/Integration/DSC_SqlScriptQuery.config.ps1 @@ -27,6 +27,7 @@ else InstanceName = 'DSCSQLTEST' Database1Name = 'ScriptDatabase3' Database2Name = 'ScriptDatabase4' + Database3Name = '$(DatabaseName)' GetQuery = @' SELECT Name FROM sys.databases WHERE Name = '$(DatabaseName)' FOR JSON AUTO @@ -112,3 +113,67 @@ Configuration DSC_SqlScriptQuery_RunSqlScriptQueryAsSqlUser_Config } } } + + +<# + .SYNOPSIS + Runs the SQL query with variables disabled. + + .NOTES + When the test is run with the DisableVariables parameter the ConfigData variable as it apears in the query will be used as the database name. + For example if the ConfigData database name is written as $(DatabaseName) in the T-SQL then the name of the database created will be $(DatabaseName). + It might appear odd but it is a valid database name. + + The SqlScript resource has a similar test for DisableVariables. The integration test run order has SqlScriptQuery running after SqlScript. + The SqlScript test is written to remove the database because if the database already existed the SqlScriptQuery test would be invalid as + the TestQuery would see an existing database and therefore not run the SetQuery. +#> +Configuration DSC_SqlScriptQuery_RunSqlScriptQueryWithVariablesDisabled_Config +{ + Import-DscResource -ModuleName 'SqlServerDsc' + + node $AllNodes.NodeName + { + SqlScriptQuery 'Integration_Test' + { + ServerName = $Node.ServerName + InstanceName = $Node.InstanceName + + GetQuery = $Node.GetQuery + TestQuery = $Node.TestQuery + SetQuery = $Node.SetQuery + DisableVariables = $true + QueryTimeout = 30 + Credential = New-Object ` + -TypeName System.Management.Automation.PSCredential ` + -ArgumentList @($Node.SqlLogin_Username, (ConvertTo-SecureString -String $Node.SqlLogin_Password -AsPlainText -Force)) + } + } +} + +<# + .SYNOPSIS + Remove the database created from the DisabledVariables test. + + .NOTES + At this point the database is no longer needed by any other resources or tests so it will be removed. +#> +Configuration DSC_SqlScriptQuery_RemoveDatabase3_Config +{ + Import-DscResource -ModuleName 'SqlServerDsc' + + node $AllNodes.NodeName + { + SqlDatabase 'RemoveDatabase3' + { + Ensure = 'Absent' + ServerName = $Node.ServerName + InstanceName = $Node.InstanceName + Name = $Node.Database3Name + + PsDscRunAsCredential = New-Object ` + -TypeName System.Management.Automation.PSCredential ` + -ArgumentList @($Node.Admin_UserName, (ConvertTo-SecureString -String $Node.Admin_Password -AsPlainText -Force)) + } + } +}