Modules/AzureDevOpsDsc.Common/Resources/Functions/Public/AzDoWorkItemQuery/Get-AzDoWorkItemQuery.ps1
|
<#
.SYNOPSIS Retrieves the current state of an Azure DevOps shared work item query. .DESCRIPTION Looks the query up live (with $expand=all, which is what populates wiql, columns and sortColumns) and compares it against the desired state. Two comparison rules are worth knowing about: WIQL is compared in normalized form. The Queries API does not return the WIQL it was given - it re-indents, re-wraps and re-cases it - so comparing the raw strings would report drift on every Test(), forever, even when nothing had changed. See ConvertTo-NormalizedWiql. Properties the configuration does not specify are not compared. A configuration that sets only Wiql is stating an intent about the WIQL, not an intent that the query should have no columns; treating an unspecified property as "must be empty" would strip display columns from every query the configuration touched. .PARAMETER ProjectName The name of the Azure DevOps project. .PARAMETER Path The full path of the query, including the root and any folders. .PARAMETER Wiql The desired WIQL statement. .PARAMETER QueryType The desired query type: 'flat', 'tree' or 'oneHop'. .PARAMETER Columns The desired display columns, as field reference names. .PARAMETER SortColumns The desired sort order: @{ Field = 'System.Id'; Descending = $false }. .PARAMETER LookupResult The lookup result from a previous call, supplied by the DSC base class. .PARAMETER Ensure The desired state, supplied by the DSC base class. .PARAMETER Force Forces the operation, supplied by the DSC base class. .EXAMPLE Get-AzDoWorkItemQuery -ProjectName 'Contoso' -Path 'Shared Queries/Active Bugs' -Wiql $wiql #> Function Get-AzDoWorkItemQuery { [CmdletBinding()] [OutputType([System.Management.Automation.PSObject[]])] param ( [Parameter(Mandatory = $true)] [Alias('Name')] [System.String]$ProjectName, [Parameter(Mandatory = $true)] [Alias('QueryPath')] [System.String]$Path, [Parameter()] [System.String]$Wiql, [Parameter()] [System.String]$QueryType, [Parameter()] [System.String[]]$Columns, [Parameter()] [HashTable[]]$SortColumns, [Parameter()] [HashTable]$LookupResult, [Parameter()] [Ensure]$Ensure, [Parameter()] [System.Management.Automation.SwitchParameter]$Force ) Write-Verbose "[Get-AzDoWorkItemQuery] Started." $result = @{ Ensure = [Ensure]::Absent propertiesChanged = @() status = $null reason = $null path = (Format-AzDoQueryPath -Path $Path) } $organization = Get-AzDoOrganizationName $normalizedPath = $result.path if ([String]::IsNullOrWhiteSpace($normalizedPath)) { Write-Error "[Get-AzDoWorkItemQuery] A query path must be supplied." $result.status = [DSCGetSummaryState]::Error $result.reason = 'EmptyPath' return $result } $query = Get-DevOpsQuery -Organization $organization -ProjectName $ProjectName -Path $normalizedPath -Expand 'all' if ($null -eq $query) { Write-Verbose "[Get-AzDoWorkItemQuery] Query '$normalizedPath' does not exist." $result.status = [DSCGetSummaryState]::NotFound return $result } # A folder occupying the query's path is a conflict the resource must not resolve on its # own - removing it would delete every query beneath it. if ($query.isFolder) { Write-Error "[Get-AzDoWorkItemQuery] The path '$normalizedPath' exists in project '$ProjectName' but is a folder, not a query. Refusing to manage it as a query." $result.status = [DSCGetSummaryState]::Error $result.reason = 'PathIsAFolder' $result.liveCache = $query return $result } $result.liveCache = $query $result.Ensure = [Ensure]::Present $propertiesChanged = @() # WIQL: compare normalized forms, but never store the normalized form back. if ($PSBoundParameters.ContainsKey('Wiql') -and (-not [String]::IsNullOrWhiteSpace($Wiql))) { $desiredWiql = ConvertTo-NormalizedWiql -Wiql $Wiql $currentWiql = ConvertTo-NormalizedWiql -Wiql $query.wiql if ($desiredWiql -ne $currentWiql) { Write-Verbose "[Get-AzDoWorkItemQuery] WIQL differs for '$normalizedPath'." $propertiesChanged += 'Wiql' } } if ($PSBoundParameters.ContainsKey('QueryType') -and (-not [String]::IsNullOrWhiteSpace($QueryType))) { if ($QueryType -ne [String]$query.queryType) { Write-Verbose "[Get-AzDoWorkItemQuery] QueryType differs for '$normalizedPath' (desired '$QueryType', current '$($query.queryType)')." $propertiesChanged += 'QueryType' } } # Column order is meaningful - it is the order they appear in the results grid - so these # are compared as ordered sequences rather than as sets. if ($PSBoundParameters.ContainsKey('Columns') -and $Columns.Count -gt 0) { $currentColumns = @($query.columns | ForEach-Object { $_.referenceName }) if (($Columns -join '|') -ne ($currentColumns -join '|')) { Write-Verbose "[Get-AzDoWorkItemQuery] Columns differ for '$normalizedPath'." $propertiesChanged += 'Columns' } } if ($PSBoundParameters.ContainsKey('SortColumns') -and $SortColumns.Count -gt 0) { $desiredSort = @($SortColumns | ForEach-Object { '{0}:{1}' -f $_.Field, ([bool]$_.Descending) }) $currentSort = @($query.sortColumns | ForEach-Object { '{0}:{1}' -f $_.field.referenceName, ([bool]$_.descending) }) if (($desiredSort -join '|') -ne ($currentSort -join '|')) { Write-Verbose "[Get-AzDoWorkItemQuery] SortColumns differ for '$normalizedPath'." $propertiesChanged += 'SortColumns' } } $result.propertiesChanged = $propertiesChanged if ($propertiesChanged.Count -gt 0) { $result.status = [DSCGetSummaryState]::Changed } else { $result.status = [DSCGetSummaryState]::Unchanged } Write-Verbose "[Get-AzDoWorkItemQuery] Query '$normalizedPath' status: $($result.status)." return $result } |