Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Build and deploy AI applications on Azure AI Foundry using Microsoft's model catalog and AI services
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
foundry-agent/create/scripts/resolve-project-id.ps1
1<#2.SYNOPSIS3Resolves a Foundry project ARM resource ID from a Foundry project endpoint.4.DESCRIPTION5Uses the endpoint only to obtain lookup keys for Azure CLI queries. The6resource ID printed by this script is always the `id` returned by Azure,7never a locally constructed ARM resource ID.8.EXAMPLE9./resolve-project-id.ps1 -Endpoint "https://my-account.services.ai.azure.com/api/projects/my-project"10.EXAMPLE11./resolve-project-id.ps1 -Endpoint "https://my-account.services.ai.azure.com/api/projects/my-project" -Output json12#>1314[CmdletBinding()]15param(16[Parameter(Mandatory = $true)]17[string]$Endpoint,1819[string]$Subscription,2021[string]$ResourceGroup,2223[string]$AccountName,2425[string]$ProjectName,2627[ValidateSet("id", "json")]28[string]$Output = "id"29)3031$ErrorActionPreference = "Stop"3233function Stop-Fatal {34param([string]$Message)35[Console]::Error.WriteLine("[ERROR] $Message")36exit 137}3839function Normalize-Endpoint {40param([string]$Value)41if (-not $Value) { return "" }42return $Value.Trim().TrimEnd("/")43}4445function Add-SubscriptionArg {46param([string[]]$CommandArgs)47if ($Subscription) {48return $CommandArgs + @("--subscription", $Subscription)49}50return $CommandArgs51}5253function Invoke-AzJson {54param([string[]]$CommandArgs)55$raw = & az @CommandArgs 2>&156if ($LASTEXITCODE -ne 0) {57throw "az $($CommandArgs -join ' ') failed: $($raw -join "`n")"58}59if (-not $raw) { return $null }60return (($raw -join "`n") | ConvertFrom-Json -ErrorAction Stop)61}6263function Get-ProjectEndpoints {64param($Project)65$values = @()66if ($Project -and $Project.properties -and $Project.properties.endpoints) {67foreach ($property in $Project.properties.endpoints.PSObject.Properties) {68if ($property.Value -is [string] -and $property.Value) {69$values += (Normalize-Endpoint $property.Value)70}71}72}73return $values74}7576function Endpoint-MatchesProject {77param($Project, [string]$ExpectedEndpoint)78foreach ($candidate in (Get-ProjectEndpoints $Project)) {79if ($candidate -eq $ExpectedEndpoint) {80return $true81}82}83return $false84}8586if (-not (Get-Command az -ErrorAction SilentlyContinue)) {87Stop-Fatal "Azure CLI 'az' was not found on PATH."88}8990$normalizedEndpoint = Normalize-Endpoint $Endpoint91try {92$endpointUri = [System.Uri]$normalizedEndpoint93} catch {94Stop-Fatal "Endpoint is not a valid URI: $Endpoint"95}9697if (-not $endpointUri.Scheme.StartsWith("http")) {98Stop-Fatal "Endpoint must be an http or https URI."99}100101if (-not $ProjectName) {102$segments = @($endpointUri.AbsolutePath.Trim("/").Split("/", [System.StringSplitOptions]::RemoveEmptyEntries))103for ($i = 0; $i -lt $segments.Count; $i++) {104if ($segments[$i] -ieq "projects" -and ($i + 1) -lt $segments.Count) {105$ProjectName = [System.Uri]::UnescapeDataString($segments[$i + 1])106break107}108}109}110111if (-not $ProjectName) {112Stop-Fatal "Could not read the project name from the endpoint path. Re-run with -ProjectName."113}114115if (-not $AccountName) {116$hostParts = @($endpointUri.Host.Split("."))117if ($hostParts.Count -gt 0 -and $endpointUri.Host.EndsWith(".services.ai.azure.com", [System.StringComparison]::OrdinalIgnoreCase)) {118$AccountName = $hostParts[0]119}120}121122if (-not $AccountName) {123Stop-Fatal "Could not read the account name from the endpoint host. Re-run with -AccountName."124}125126if (-not $ResourceGroup) {127try {128$accounts = Invoke-AzJson (Add-SubscriptionArg @("cognitiveservices", "account", "list", "-o", "json"))129} catch {130Stop-Fatal $_.Exception.Message131}132133$matches = @($accounts | Where-Object {134($_.name -ieq $AccountName) -or135($_.properties.customSubDomainName -ieq $AccountName)136})137138if ($matches.Count -eq 0) {139Stop-Fatal "Could not find a Cognitive Services account matching '$AccountName'. Re-run with -ResourceGroup and -AccountName if the endpoint uses a custom host."140}141142if ($matches.Count -gt 1) {143$choices = ($matches | ForEach-Object { "$($_.resourceGroup)/$($_.name)" }) -join ", "144Stop-Fatal "Multiple accounts matched '$AccountName': $choices. Re-run with -ResourceGroup."145}146147$ResourceGroup = $matches[0].resourceGroup148$AccountName = $matches[0].name149}150151$project = $null152try {153$project = Invoke-AzJson (Add-SubscriptionArg @(154"cognitiveservices", "account", "project", "show",155"-g", $ResourceGroup,156"-n", $AccountName,157"--project-name", $ProjectName,158"-o", "json"159))160} catch {161try {162$projects = Invoke-AzJson (Add-SubscriptionArg @(163"cognitiveservices", "account", "project", "list",164"-g", $ResourceGroup,165"-n", $AccountName,166"-o", "json"167))168$project = @($projects | Where-Object { Endpoint-MatchesProject $_ $normalizedEndpoint }) | Select-Object -First 1169} catch {170Stop-Fatal $_.Exception.Message171}172}173174if (-not $project) {175Stop-Fatal "Could not resolve a Foundry project for endpoint '$normalizedEndpoint'."176}177178$projectEndpoints = @(Get-ProjectEndpoints $project)179if ($projectEndpoints.Count -gt 0 -and -not (Endpoint-MatchesProject $project $normalizedEndpoint)) {180Stop-Fatal "Resolved project endpoint metadata did not match '$normalizedEndpoint'."181}182183if (-not $project.id) {184Stop-Fatal "Azure returned a project object without an id."185}186187if ($Output -eq "json") {188[ordered]@{189id = $project.id190endpoint = if ($projectEndpoints.Count -gt 0) { $projectEndpoints[0] } else { $normalizedEndpoint }191resourceGroup = $ResourceGroup192accountName = $AccountName193projectName = $ProjectName194} | ConvertTo-Json -Depth 5195} else {196Write-Output $project.id197}198