-
Notifications
You must be signed in to change notification settings - Fork 227
SqlRole: Get/Test always complete and fix parameter checks #2459
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -50,15 +50,14 @@ function Get-TargetResource | |
| $ServerRoleName | ||
| ) | ||
|
|
||
| $sqlServerObject = Connect-SQL -ServerName $ServerName -InstanceName $InstanceName -ErrorAction 'Stop' | ||
| $sqlServerObject = Connect-SQL -ServerName $ServerName -InstanceName $InstanceName -ErrorAction 'SilentlyContinue' | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not let connection failures look like an absent role. With Please preserve a failure signal and have 🤖 Prompt for AI Agents |
||
| $ensure = 'Absent' | ||
| $membersInRole = $null | ||
|
|
||
| if ($sqlServerObject) | ||
| { | ||
| Write-Verbose -Message ( | ||
| $script:localizedData.GetProperties ` | ||
| -f $ServerRoleName | ||
| $script:localizedData.GetProperties -f $ServerRoleName | ||
| ) | ||
|
|
||
| if ($sqlServerRoleObject = $sqlServerObject.Roles[$ServerRoleName]) | ||
|
|
@@ -70,10 +69,8 @@ function Get-TargetResource | |
| } | ||
| catch | ||
| { | ||
| $errorMessage = $script:localizedData.EnumMemberNamesServerRoleGetError ` | ||
| -f $ServerName, $InstanceName, $ServerRoleName | ||
|
|
||
| New-InvalidOperationException -Message $errorMessage -ErrorRecord $_ | ||
| Write-Verbose -Message ($script:localizedData.EnumMemberNamesServerRoleGetError ` | ||
| -f $ServerName, $InstanceName, $ServerRoleName) | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -237,7 +234,7 @@ function Set-TargetResource | |
|
|
||
| $correctedParameters = Get-CorrectedMemberParameters @originalParameters | ||
|
|
||
| if ($Members) | ||
| if ($PSBoundParameters.ContainsKey('Members')) | ||
| { | ||
| $memberNamesInRoleObject = $sqlServerObject.Roles[$ServerRoleName].EnumMemberNames() | ||
|
|
||
|
|
@@ -263,7 +260,7 @@ function Set-TargetResource | |
| } | ||
| else | ||
| { | ||
| if ($MembersToInclude) | ||
| if ($PSBoundParameters.ContainsKey('MembersToInclude')) | ||
| { | ||
| $memberNamesInRoleObject = $sqlServerObject.Roles[$ServerRoleName].EnumMemberNames() | ||
|
|
||
|
|
@@ -278,7 +275,7 @@ function Set-TargetResource | |
| } | ||
| } | ||
|
|
||
| if ($MembersToExclude) | ||
| if ($PSBoundParameters.ContainsKey('MembersToExclude')) | ||
| { | ||
| $memberNamesInRoleObject = $sqlServerObject.Roles[$ServerRoleName].EnumMemberNames() | ||
|
|
||
|
|
@@ -428,9 +425,9 @@ function Test-TargetResource | |
| } | ||
| else | ||
| { | ||
| if ($Members) | ||
| if ($PSBoundParameters.ContainsKey('Members')) | ||
| { | ||
| if ( $null -ne (Compare-Object -ReferenceObject $getTargetResourceResult.Members -DifferenceObject $correctedParameters.Members)) | ||
| if ($null -ne (Compare-Object -ReferenceObject $getTargetResourceResult.Members -DifferenceObject $correctedParameters.Members)) | ||
|
Comment on lines
+428
to
+430
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Description: Verify PowerShell Compare-Object behavior with empty/null desired member lists.
# Expected: These commands demonstrate why the resource should normalize/guard empty lists.
pwsh -NoProfile -Command "Compare-Object -ReferenceObject @('CONTOSO\User') -DifferenceObject @()"
pwsh -NoProfile -Command "Compare-Object -ReferenceObject @('CONTOSO\User') -DifferenceObject \$null"Repository: dsccommunity/SqlServerDsc Length of output: 246 🏁 Script executed: cat -n source/DSCResources/DSC_SqlRole/DSC_SqlRole.psm1 | head -450 | tail -50Repository: dsccommunity/SqlServerDsc Length of output: 2282 🏁 Script executed: # Find Get-TargetResource function and how Members is returned
grep -n "function Get-TargetResource" source/DSCResources/DSC_SqlRole/DSC_SqlRole.psm1Repository: dsccommunity/SqlServerDsc Length of output: 99 🏁 Script executed: sed -n '31,150p' source/DSCResources/DSC_SqlRole/DSC_SqlRole.psm1Repository: dsccommunity/SqlServerDsc Length of output: 3181 🏁 Script executed: grep -n "function Test-TargetResource" source/DSCResources/DSC_SqlRole/DSC_SqlRole.psm1Repository: dsccommunity/SqlServerDsc Length of output: 101 🏁 Script executed: sed -n '325,410p' source/DSCResources/DSC_SqlRole/DSC_SqlRole.psm1Repository: dsccommunity/SqlServerDsc Length of output: 2396 🏁 Script executed: grep -n "function Get-CorrectedMemberParameters" source/DSCResources/DSC_SqlRole/DSC_SqlRole.psm1Repository: dsccommunity/SqlServerDsc Length of output: 111 🏁 Script executed: sed -n '650,750p' source/DSCResources/DSC_SqlRole/DSC_SqlRole.psm1Repository: dsccommunity/SqlServerDsc Length of output: 1029 🏁 Script executed: # Verify the behavior of type casting $null to [System.String[]]
pwsh -NoProfile -Command '[System.String[]]$null | ForEach-Object { "Value: $_"; "Length: $($_.Length)" } ; if ($null -eq ([System.String[]]$null)) { "Result is null" } else { "Result is not null" }'Repository: dsccommunity/SqlServerDsc Length of output: 101 🏁 Script executed: # Verify Compare-Object with $null values specifically
pwsh -NoProfile -Command "
try {
Compare-Object -ReferenceObject @('CONTOSO\User') -DifferenceObject \$null
} catch {
Write-Host 'Error caught: ' + \$_.Exception.Message
}
"Repository: dsccommunity/SqlServerDsc Length of output: 158 🏁 Script executed: # Verify the actual scenario: what happens at line 430 when either side is $null
pwsh -NoProfile -Command "
# Simulate the scenario
\$getTargetResourceResult = @{ Members = \$null }
\$correctedParameters = @{ Members = \$null }
# Try the current code path
try {
\$result = \$null -ne (Compare-Object -ReferenceObject \$getTargetResourceResult.Members -DifferenceObject \$correctedParameters.Members)
Write-Host \"Result: \$result\"
} catch {
Write-Host \"Error: \$(\$_.Exception.Message)\"
}
# Now test with empty arrays instead
\$getTargetResourceResult.Members = @()
\$correctedParameters.Members = @()
\$result = \$null -ne (Compare-Object -ReferenceObject \$getTargetResourceResult.Members -DifferenceObject \$correctedParameters.Members)
Write-Host \"With empty arrays, result: \$result\"
"Repository: dsccommunity/SqlServerDsc Length of output: 180 🏁 Script executed: # Verify what happens with actual sysadmin role with no members
pwsh -NoProfile -Command "
# Simulating the actual code flow for sysadmin role with no members
\$Members = \$null
\$MembersToInclude = \$null
\$MembersToExclude = \$null
\$ServerRoleName = 'sysadmin'
# This simulates Get-CorrectedMemberParameters
\$correctedParameters = @{
Members = [System.String[]](\$Members)
MembersToInclude = [System.String[]](\$MembersToInclude)
MembersToExclude = [System.String[]](\$MembersToExclude)
}
Write-Host \"Members type: \$(\$correctedParameters.Members.GetType())\"
Write-Host \"Members is null: \$(\$null -eq \$correctedParameters.Members)\"
Write-Host \"Members value: '\$(\$correctedParameters.Members)'\"
"Repository: dsccommunity/SqlServerDsc Length of output: 379 🏁 Script executed: # Check if there are tests for this scenario and if the issue manifests
rg -A 5 "Compare-Object" source/DSCResources/DSC_SqlRole/DSC_SqlRole.psm1Repository: dsccommunity/SqlServerDsc Length of output: 442 🏁 Script executed: # Check if there are unit tests for this scenario
find tests -name "*SqlRole*" -type fRepository: dsccommunity/SqlServerDsc Length of output: 214 🏁 Script executed: # Search for test cases with Members parameter
rg -B 2 -A 5 "Members.*\`$null\|Members.*@\(\)" tests/Unit/DSC_SqlRole.Tests.ps1 | head -100Repository: dsccommunity/SqlServerDsc Length of output: 51 🏁 Script executed: # Check for test cases involving Members parameter
rg "Members" tests/Unit/DSC_SqlRole.Tests.ps1 -cRepository: dsccommunity/SqlServerDsc Length of output: 72 🏁 Script executed: grep -n "Members" tests/Unit/DSC_SqlRole.Tests.ps1 | head -30Repository: dsccommunity/SqlServerDsc Length of output: 2821 Normalize empty/null member lists before When comparing members, Proposed fix if ($PSBoundParameters.ContainsKey('Members'))
{
- if ($null -ne (Compare-Object -ReferenceObject $getTargetResourceResult.Members -DifferenceObject $correctedParameters.Members))
+ $currentMembers = if ($null -eq $getTargetResourceResult.Members)
+ {
+ @()
+ }
+ else
+ {
+ @($getTargetResourceResult.Members)
+ }
+
+ $desiredMembers = if ($null -eq $correctedParameters.Members)
+ {
+ @()
+ }
+ else
+ {
+ @($correctedParameters.Members)
+ }
+
+ $membersAreDifferent = $currentMembers.Count -ne $desiredMembers.Count
+
+ if (-not $membersAreDifferent -and $currentMembers.Count -gt 0)
+ {
+ $membersAreDifferent = $null -ne (
+ Compare-Object -ReferenceObject $currentMembers -DifferenceObject $desiredMembers
+ )
+ }
+
+ if ($membersAreDifferent)
{
Write-Verbose -Message (
$script:localizedData.DesiredMembersNotPresent `🤖 Prompt for AI Agents |
||
| { | ||
| Write-Verbose -Message ( | ||
| $script:localizedData.DesiredMembersNotPresent ` | ||
|
|
@@ -442,7 +439,7 @@ function Test-TargetResource | |
| } | ||
| else | ||
| { | ||
| if ($MembersToInclude) | ||
| if ($PSBoundParameters.ContainsKey('MembersToInclude')) | ||
| { | ||
| foreach ($memberToInclude in $correctedParameters.MembersToInclude) | ||
| { | ||
|
|
@@ -458,7 +455,7 @@ function Test-TargetResource | |
| } | ||
| } | ||
|
|
||
| if ($MembersToExclude) | ||
| if ($PSBoundParameters.ContainsKey('MembersToExclude')) | ||
| { | ||
| foreach ($memberToExclude in $correctedParameters.MembersToExclude) | ||
| { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -311,24 +311,24 @@ Describe "DSC_SqlRole\Get-TargetResource" -Tag 'Get' { | |
| $mockInvalidOperationForEnumMethod = $true | ||
| } | ||
|
|
||
| It 'Should throw the correct error' { | ||
| It 'Should not throw an error and return the correct result' { | ||
| InModuleScope -ScriptBlock { | ||
| Set-StrictMode -Version 1.0 | ||
|
|
||
| $mockTestParameters.ServerRoleName = 'AdminSqlForBI' | ||
|
|
||
| $mockErrorMessage = $script:localizedData.EnumMemberNamesServerRoleGetError -f @( | ||
| 'localhost', | ||
| 'MSSQLSERVER', | ||
| 'AdminSqlForBI' | ||
| ) | ||
| $result = Get-TargetResource @mockTestParameters | ||
|
|
||
| { Get-TargetResource @mockTestParameters } | Should -Throw -ExpectedMessage ('*' + $mockErrorMessage + '*') | ||
| $result.ServerName | Should -Be $mockTestParameters.ServerName | ||
| $result.InstanceName | Should -Be $mockTestParameters.InstanceName | ||
| $result.ServerRoleName | Should -Be $mockTestParameters.ServerRoleName | ||
| $result.Ensure | Should -Be 'Absent' | ||
| $result.Members | Should -BeNullOrEmpty | ||
| $result.MembersToInclude | Should -BeNullOrEmpty | ||
| $result.MembersToExclude | Should -BeNullOrEmpty | ||
|
Comment on lines
+314
to
+328
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Assert the role remains present when enumeration fails. This test now encodes the false state from 🧪 Proposed test expectation update- $result.Ensure | Should -Be 'Absent'
+ $result.Ensure | Should -Be 'Present'
$result.Members | Should -BeNullOrEmpty🤖 Prompt for AI Agents |
||
| } | ||
| } | ||
|
|
||
| It 'Should call the mock function Connect-SQL' { | ||
| Should -Invoke -CommandName Connect-SQL -Exactly -Times 1 -Scope Context | ||
| Should -Invoke -CommandName Connect-SQL -Exactly -Times 1 -Scope It | ||
| } | ||
| } | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add an issue reference to the first
SqlRolebullet.Line 21 is missing an issue link while the related
SqlRolefix entry on Line 22 includes one.Suggested fix
As per coding guidelines, "Reference issues using format issue #<issue_number> in CHANGELOG.md".
📝 Committable suggestion
🤖 Prompt for AI Agents