Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Deploy, evaluate, and manage AI agents end-to-end on Microsoft Azure AI Foundry
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