Modules/AzureDevOpsDsc.Common/Api/Functions/Private/Helper/Get-AzDoApiUri.ps1
|
<#
.SYNOPSIS Resolves the base URL for an Azure DevOps REST API service. .DESCRIPTION Every private API function builds its request URL against one of a handful of per-service hostnames (dev.azure.com, vssps.dev.azure.com, vsaex.dev.azure.com, and so on). Today those hostnames are inlined at each call site. This helper centralizes that resolution so future callers - and a future on-premise (Azure DevOps Server) code path - have one place to change. When -ServerUrl is not supplied, the function returns the Azure DevOps Services (cloud) base URL for the requested -Service, built from -OrganizationName (which defaults to Get-AzDoOrganizationName). The organization name is URL-escaped exactly once. When -ServerUrl is supplied, it is treated as an on-premise collection URL (for example 'https://tfs.contoso.com/tfs/DefaultCollection'). Azure DevOps Server does not expose the per-service subdomains that Azure DevOps Services uses - every service is reached through the same collection URL - so the function returns -ServerUrl (trailing slash trimmed) for every service that has a Server-side equivalent. Entitlements and Audit have no Server equivalent and the function throws a terminating error naming the unsupported service. The returned base URL never has a trailing slash, so callers can safely append "/_apis/...". .PARAMETER Service The Azure DevOps REST API service to resolve a base URL for. .PARAMETER OrganizationName The Azure DevOps organization name (cloud only). Defaults to Get-AzDoOrganizationName. Ignored when -ServerUrl is supplied. .PARAMETER ServerUrl The base collection URL of an on-premise Azure DevOps Server instance, for example 'https://tfs.contoso.com/tfs/DefaultCollection'. When supplied, must be an absolute http or https URI. .EXAMPLE Get-AzDoApiUri -Service Core -OrganizationName 'contoso' Returns 'https://dev.azure.com/contoso'. .EXAMPLE Get-AzDoApiUri -Service Identity -OrganizationName 'contoso' Returns 'https://vssps.dev.azure.com/contoso'. .EXAMPLE Get-AzDoApiUri -Service Core -ServerUrl 'https://tfs.contoso.com/tfs/DefaultCollection/' Returns 'https://tfs.contoso.com/tfs/DefaultCollection'. .EXAMPLE Get-AzDoApiUri -Service Entitlements -ServerUrl 'https://tfs.contoso.com/tfs/DefaultCollection' Throws: the Entitlements service is not supported on Azure DevOps Server. #> Function Get-AzDoApiUri { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [ValidateSet('Core', 'Identity', 'Entitlements', 'Feeds', 'Audit', 'Release')] [String]$Service, [Parameter(Mandatory = $false)] [String]$OrganizationName, [Parameter(Mandatory = $false)] [String]$ServerUrl ) # Services with no Azure DevOps Server equivalent. Kept as data rather than a # switch-case so the "not supported" message stays consistent across services. $script:ServerUnsupportedServices = @('Entitlements', 'Audit') if (-not [String]::IsNullOrWhiteSpace($ServerUrl)) { $parsedUri = $null $isAbsoluteUri = [System.Uri]::TryCreate($ServerUrl, [System.UriKind]::Absolute, [ref]$parsedUri) if (-not $isAbsoluteUri -or ($parsedUri.Scheme -ne 'http' -and $parsedUri.Scheme -ne 'https')) { throw "Get-AzDoApiUri: -ServerUrl '$ServerUrl' is not a valid absolute http or https URI." } if ($Service -in $script:ServerUnsupportedServices) { throw "Get-AzDoApiUri: the '$Service' service is not supported on Azure DevOps Server (on-premise collections have no equivalent endpoint)." } return $ServerUrl.TrimEnd('/') } if ([String]::IsNullOrWhiteSpace($OrganizationName)) { $OrganizationName = Get-AzDoOrganizationName } if ([String]::IsNullOrWhiteSpace($OrganizationName)) { throw 'Get-AzDoApiUri: unable to resolve an organization name. Supply -OrganizationName or set the global organization name.' } # Escape once here; never re-escape the value this function returns. $escapedOrganizationName = [System.Uri]::EscapeDataString($OrganizationName) switch ($Service) { 'Core' { return "https://dev.azure.com/$escapedOrganizationName" } 'Identity' { return "https://vssps.dev.azure.com/$escapedOrganizationName" } 'Entitlements' { return "https://vsaex.dev.azure.com/$escapedOrganizationName" } 'Feeds' { return "https://feeds.dev.azure.com/$escapedOrganizationName" } 'Audit' { return "https://auditservice.dev.azure.com/$escapedOrganizationName" } 'Release' { return "https://vsrm.dev.azure.com/$escapedOrganizationName" } } } |