diff --git a/CHANGELOG.md b/CHANGELOG.md index d7eed4ab8..0667493f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- SqlScript + - Added integration test configuration that creates script files and executes + the resource in a single configuration using `DependsOn`. + ## [17.5.1] - 2026-02-05 ### Added diff --git a/tests/Integration/Resources/DSC_SqlScript.Integration.Tests.ps1 b/tests/Integration/Resources/DSC_SqlScript.Integration.Tests.ps1 index 0280fb4ba..7c068d773 100644 --- a/tests/Integration/Resources/DSC_SqlScript.Integration.Tests.ps1 +++ b/tests/Integration/Resources/DSC_SqlScript.Integration.Tests.ps1 @@ -334,6 +334,132 @@ Describe "$($script:dscResourceName)_Integration" -Tag @('Integration_SQL2016', } } + Context ('When using configuration <_>') -ForEach @( + "$($script:dscResourceName)_RunSqlScriptAsWindowsUserWithDependencies_Config" + ) { + BeforeAll { + $configurationName = $_ + } + + AfterEach { + Wait-ForIdleLcm + } + + It 'Should compile and apply the MOF without throwing' { + $configurationParameters = @{ + OutputPath = $TestDrive + # The variable $ConfigurationData was dot-sourced above. + ConfigurationData = $ConfigurationData + } + + $null = & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + $null = Start-DscConfiguration @startDscConfigurationParameters + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + $script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction 'Stop' + } + + 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":"ScriptDatabase4"}] + ``` + + This could have been easier by just having this test + $resourceCurrentState.GetResult | Should -Match 'ScriptDatabase4' + 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.Database4Name + + $resourceCurrentState.ServerName | Should -Be $ConfigurationData.AllNodes.ServerName + $resourceCurrentState.InstanceName | Should -Be $ConfigurationData.AllNodes.InstanceName + $resourceCurrentState.GetFilePath | Should -Be $ConfigurationData.AllNodes.GetSqlScriptPath2 + $resourceCurrentState.TestFilePath | Should -Be $ConfigurationData.AllNodes.TestSqlScriptPath2 + $resourceCurrentState.SetFilePath | Should -Be $ConfigurationData.AllNodes.SetSqlScriptPath2 + } + + It 'Should return $true when Test-DscConfiguration is run' { + Test-DscConfiguration -Verbose -ErrorAction 'Stop' | Should -Be 'True' + } + } + + Context ('When using configuration <_>') -ForEach @( + "$($script:dscResourceName)_RemoveDatabase4_Config" + ) { + BeforeAll { + $configurationName = $_ + } + + AfterEach { + Wait-ForIdleLcm + } + + It 'Should compile and apply the MOF without throwing' { + $configurationParameters = @{ + OutputPath = $TestDrive + # The variable $ConfigurationData was dot-sourced above. + ConfigurationData = $ConfigurationData + } + + $null = & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + $null = Start-DscConfiguration @startDscConfigurationParameters + } + } + Context ('When using configuration <_>') -ForEach @( "$($script:dscResourceName)_RemoveDatabase3_Config" ) { diff --git a/tests/Integration/Resources/DSC_SqlScript.config.ps1 b/tests/Integration/Resources/DSC_SqlScript.config.ps1 index 4feb8c035..4abadcb07 100644 --- a/tests/Integration/Resources/DSC_SqlScript.config.ps1 +++ b/tests/Integration/Resources/DSC_SqlScript.config.ps1 @@ -29,11 +29,16 @@ else Database1Name = 'ScriptDatabase1' Database2Name = 'ScriptDatabase2' Database3Name = '$(DatabaseName)' + Database4Name = 'ScriptDatabase4' GetSqlScriptPath = Join-Path -Path $env:SystemDrive -ChildPath ([System.IO.Path]::GetRandomFileName()) SetSqlScriptPath = Join-Path -Path $env:SystemDrive -ChildPath ([System.IO.Path]::GetRandomFileName()) TestSqlScriptPath = Join-Path -Path $env:SystemDrive -ChildPath ([System.IO.Path]::GetRandomFileName()) + GetSqlScriptPath2 = Join-Path -Path $env:SystemDrive -ChildPath ([System.IO.Path]::GetRandomFileName()) + SetSqlScriptPath2 = Join-Path -Path $env:SystemDrive -ChildPath ([System.IO.Path]::GetRandomFileName()) + TestSqlScriptPath2 = Join-Path -Path $env:SystemDrive -ChildPath ([System.IO.Path]::GetRandomFileName()) + GetSqlScript = @' SELECT Name FROM sys.databases WHERE Name = '$(DatabaseName)' FOR JSON AUTO '@ @@ -294,6 +299,148 @@ Configuration DSC_SqlScript_RunSqlScriptWithVariablesDisabled_Config } } +<# + .SYNOPSIS + Creates the script files and runs the SQL script as a Windows User + in the same configuration using DependsOn. +#> +Configuration DSC_SqlScript_RunSqlScriptAsWindowsUserWithDependencies_Config +{ + Import-DscResource -ModuleName 'xPSDesiredStateConfiguration' -ModuleVersion '9.1.0' + Import-DscResource -ModuleName 'SqlServerDsc' + + node $AllNodes.NodeName + { + xScript 'CreateFile_GetSqlScript' + { + SetScript = { + $Using:Node.GetSqlScript | Out-File -FilePath $Using:Node.GetSqlScriptPath2 -Encoding ascii -NoClobber -Force + } + + TestScript = { + $getScriptResult = & ([ScriptBlock]::Create($GetScript)) + + return $getScriptResult.Result -eq $Using:Node.GetSqlScript + } + + GetScript = { + $fileContent = $null + + if (Test-Path -Path $Using:Node.GetSqlScriptPath2) + { + $fileContent = Get-Content -Path $Using:Node.GetSqlScriptPath2 -Raw + } + + return @{ + Result = $fileContent + } + } + } + + xScript 'CreateFile_TestSqlScript' + { + SetScript = { + $Using:Node.TestSqlScript | Out-File -FilePath $Using:Node.TestSqlScriptPath2 -Encoding ascii -NoClobber -Force + } + + TestScript = { + $getScriptResult = & ([ScriptBlock]::Create($GetScript)) + + return $getScriptResult.Result -eq $Using:Node.TestSqlScript + } + + GetScript = { + $fileContent = $null + + if (Test-Path -Path $Using:Node.TestSqlScriptPath2) + { + $fileContent = Get-Content -Path $Using:Node.TestSqlScriptPath2 -Raw + } + + return @{ + Result = $fileContent + } + } + } + + xScript 'CreateFile_SetSqlScript' + { + SetScript = { + $Using:Node.SetSqlScript | Out-File -FilePath $Using:Node.SetSqlScriptPath2 -Encoding ascii -NoClobber -Force + } + + TestScript = { + $getScriptResult = & ([ScriptBlock]::Create($GetScript)) + + return $getScriptResult.Result -eq $Using:Node.SetSqlScript + } + + GetScript = { + $fileContent = $null + + if (Test-Path -Path $Using:Node.SetSqlScriptPath2) + { + $fileContent = Get-Content -Path $Using:Node.SetSqlScriptPath2 -Raw + } + + return @{ + Result = $fileContent + } + } + } + + SqlScript 'Integration_Test' + { + Id = 'Integration_Test' + ServerName = $Node.ServerName + InstanceName = $Node.InstanceName + + GetFilePath = $Node.GetSqlScriptPath2 + TestFilePath = $Node.TestSqlScriptPath2 + SetFilePath = $Node.SetSqlScriptPath2 + Variable = @( + ('DatabaseName={0}' -f $Node.Database4Name) + ) + QueryTimeout = 30 + Encrypt = 'Optional' + + PsDscRunAsCredential = New-Object ` + -TypeName System.Management.Automation.PSCredential ` + -ArgumentList @($Node.Admin_UserName, (ConvertTo-SecureString -String $Node.Admin_Password -AsPlainText -Force)) + + DependsOn = @( + '[xScript]CreateFile_GetSqlScript' + '[xScript]CreateFile_TestSqlScript' + '[xScript]CreateFile_SetSqlScript' + ) + } + } +} + +<# + .SYNOPSIS + Remove the database created from the combined configuration test. +#> +Configuration DSC_SqlScript_RemoveDatabase4_Config +{ + Import-DscResource -ModuleName 'SqlServerDsc' + + node $AllNodes.NodeName + { + SqlDatabase 'RemoveDatabase4' + { + Ensure = 'Absent' + ServerName = $Node.ServerName + InstanceName = $Node.InstanceName + Name = $Node.Database4Name + + PsDscRunAsCredential = New-Object ` + -TypeName System.Management.Automation.PSCredential ` + -ArgumentList @($Node.Admin_UserName, (ConvertTo-SecureString -String $Node.Admin_Password -AsPlainText -Force)) + } + } +} + <# .SYNOPSIS Remove the database created from the DisabledVariables test.