From e79c367083d885a126ffa89d883444be523874cb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 22:03:52 +0000 Subject: [PATCH 1/5] Initial plan From 00b1b371db7fe7a02dd153e24c6f1555e948f15d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 22:08:01 +0000 Subject: [PATCH 2/5] Fix VMSizes-Must-Match-Template to support nested outputs Co-authored-by: psah434 <114955590+psah434@users.noreply.github.com> --- .../VMSizes-Must-Match-Template.test.ps1 | 43 ++++++++++++++-- .../Nested-Outputs-2-Levels/azureDeploy.json | 9 ++++ .../createUIDefinition.json | 49 ++++++++++++++++++ .../Nested-Outputs-3-Levels/azureDeploy.json | 9 ++++ .../createUIDefinition.json | 51 +++++++++++++++++++ 5 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 unit-tests/VMSizes-Must-Match-Template/Pass/Nested-Outputs-2-Levels/azureDeploy.json create mode 100644 unit-tests/VMSizes-Must-Match-Template/Pass/Nested-Outputs-2-Levels/createUIDefinition.json create mode 100644 unit-tests/VMSizes-Must-Match-Template/Pass/Nested-Outputs-3-Levels/azureDeploy.json create mode 100644 unit-tests/VMSizes-Must-Match-Template/Pass/Nested-Outputs-3-Levels/createUIDefinition.json diff --git a/arm-ttk/testcases/CreateUIDefinition/VMSizes-Must-Match-Template.test.ps1 b/arm-ttk/testcases/CreateUIDefinition/VMSizes-Must-Match-Template.test.ps1 index 793abf91..dc7df2ee 100644 --- a/arm-ttk/testcases/CreateUIDefinition/VMSizes-Must-Match-Template.test.ps1 +++ b/arm-ttk/testcases/CreateUIDefinition/VMSizes-Must-Match-Template.test.ps1 @@ -21,6 +21,41 @@ $MainTemplateParameters #Write-Warning "Skipping Test..." #break +# Helper function to recursively search for a pattern in nested objects +function Find-OutputProperty { + param( + [Parameter(Mandatory=$true)] + [PSObject]$Object, + + [Parameter(Mandatory=$true)] + [string]$Pattern, + + [Parameter(Mandatory=$false)] + [string]$PropertyName = $null + ) + + foreach ($prop in $Object.psobject.properties) { + $currentName = if ($PropertyName) { $PropertyName } else { $prop.Name } + + if ($prop.Value -is [string] -and $prop.Value -like $Pattern) { + # Found a matching string value + return [PSCustomObject]@{ + Name = $currentName + Value = $prop.Value + } + } + elseif ($prop.Value -is [PSCustomObject] -or $prop.Value -is [System.Collections.Specialized.OrderedDictionary]) { + # Recursively search nested objects + $result = Find-OutputProperty -Object $prop.Value -Pattern $Pattern -PropertyName $currentName + if ($result) { + return $result + } + } + } + + return $null +} + # First, find all size selectors in CreateUIDefinition. $sizeSelectors = $CreateUIDefinitionObject | Find-JsonContent -Key type -Value Microsoft.Compute.SizeSelector @@ -42,11 +77,9 @@ foreach ($selector in $sizeSelectors) { # Then walk each selector, } else { "*basics(*$($controlName)*" } - $theOutput = foreach ($out in $CreateUIDefinitionObject.parameters.outputs.psobject.properties) { - if ($out.Value -like $lookingFor) { - $out; break - } - } + + # Use the helper function to recursively search for the pattern in outputs + $theOutput = Find-OutputProperty -Object $CreateUIDefinitionObject.parameters.outputs -Pattern $lookingFor if (-not $theOutput) { Write-Error "Could not find VM SizeSelector '$($selector.Name)' in outputs" -TargetObject $selector diff --git a/unit-tests/VMSizes-Must-Match-Template/Pass/Nested-Outputs-2-Levels/azureDeploy.json b/unit-tests/VMSizes-Must-Match-Template/Pass/Nested-Outputs-2-Levels/azureDeploy.json new file mode 100644 index 00000000..4ff94a8d --- /dev/null +++ b/unit-tests/VMSizes-Must-Match-Template/Pass/Nested-Outputs-2-Levels/azureDeploy.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "parameters": { + "clusters": { + "type": "object" + } + }, + "resources": [] +} diff --git a/unit-tests/VMSizes-Must-Match-Template/Pass/Nested-Outputs-2-Levels/createUIDefinition.json b/unit-tests/VMSizes-Must-Match-Template/Pass/Nested-Outputs-2-Levels/createUIDefinition.json new file mode 100644 index 00000000..4dcbc4b4 --- /dev/null +++ b/unit-tests/VMSizes-Must-Match-Template/Pass/Nested-Outputs-2-Levels/createUIDefinition.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/0.1.2-preview/CreateUIDefinition.MultiVm.json#", + "handler": "Microsoft.Azure.CreateUIDef", + "version": "0.1.2-preview", + "parameters": { + "basics": [], + "steps": [ + { + "label": "Scheduler", + "name": "scheduler", + "bladeTitle": "Scheduler", + "bladeSubtitle": "Configure Scheduler", + "subLabel": { + "preValidation": "Configure Scheduler", + "postValidation": "Done" + }, + "elements": [ + { + "label": "Scheduler Section", + "name": "schedulerSection", + "type": "Microsoft.Common.Section", + "elements": [ + { + "label": "VM Size", + "name": "vmsize", + "toolTip": "Scheduler VM size", + "type": "Microsoft.Compute.SizeSelector", + "osPlatform": "Linux", + "count": 1, + "recommendedSizes": [ + "Standard_B1s", + "Standard_B1ms" + ] + } + ] + } + ] + } + ], + "outputs": { + "location": "[location()]", + "clusters": { + "schedulerNode": { + "sku": "[steps('scheduler').schedulerSection.vmsize]" + } + } + } + } +} diff --git a/unit-tests/VMSizes-Must-Match-Template/Pass/Nested-Outputs-3-Levels/azureDeploy.json b/unit-tests/VMSizes-Must-Match-Template/Pass/Nested-Outputs-3-Levels/azureDeploy.json new file mode 100644 index 00000000..4ff94a8d --- /dev/null +++ b/unit-tests/VMSizes-Must-Match-Template/Pass/Nested-Outputs-3-Levels/azureDeploy.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "parameters": { + "clusters": { + "type": "object" + } + }, + "resources": [] +} diff --git a/unit-tests/VMSizes-Must-Match-Template/Pass/Nested-Outputs-3-Levels/createUIDefinition.json b/unit-tests/VMSizes-Must-Match-Template/Pass/Nested-Outputs-3-Levels/createUIDefinition.json new file mode 100644 index 00000000..b1fc5687 --- /dev/null +++ b/unit-tests/VMSizes-Must-Match-Template/Pass/Nested-Outputs-3-Levels/createUIDefinition.json @@ -0,0 +1,51 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/0.1.2-preview/CreateUIDefinition.MultiVm.json#", + "handler": "Microsoft.Azure.CreateUIDef", + "version": "0.1.2-preview", + "parameters": { + "basics": [], + "steps": [ + { + "label": "Scheduler", + "name": "scheduler", + "bladeTitle": "Scheduler", + "bladeSubtitle": "Configure Scheduler", + "subLabel": { + "preValidation": "Configure Scheduler", + "postValidation": "Done" + }, + "elements": [ + { + "label": "Scheduler Section", + "name": "schedulerSection", + "type": "Microsoft.Common.Section", + "elements": [ + { + "label": "VM Size", + "name": "vmsize", + "toolTip": "Scheduler VM size", + "type": "Microsoft.Compute.SizeSelector", + "osPlatform": "Linux", + "count": 1, + "recommendedSizes": [ + "Standard_B1s", + "Standard_B1ms" + ] + } + ] + } + ] + } + ], + "outputs": { + "location": "[location()]", + "clusters": { + "slurm": { + "schedulerNode": { + "sku": "[steps('scheduler').schedulerSection.vmsize]" + } + } + } + } + } +} From dbbb8465b40c8cf007c0d64ca3f4a4794238c945 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 22:09:17 +0000 Subject: [PATCH 3/5] Add comprehensive test for multiple nested VM size selectors Co-authored-by: psah434 <114955590+psah434@users.noreply.github.com> --- .../Multiple-Nested-VMSizes/azureDeploy.json | 9 ++ .../createUIDefinition.json | 92 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 unit-tests/VMSizes-Must-Match-Template/Pass/Multiple-Nested-VMSizes/azureDeploy.json create mode 100644 unit-tests/VMSizes-Must-Match-Template/Pass/Multiple-Nested-VMSizes/createUIDefinition.json diff --git a/unit-tests/VMSizes-Must-Match-Template/Pass/Multiple-Nested-VMSizes/azureDeploy.json b/unit-tests/VMSizes-Must-Match-Template/Pass/Multiple-Nested-VMSizes/azureDeploy.json new file mode 100644 index 00000000..4ff94a8d --- /dev/null +++ b/unit-tests/VMSizes-Must-Match-Template/Pass/Multiple-Nested-VMSizes/azureDeploy.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "parameters": { + "clusters": { + "type": "object" + } + }, + "resources": [] +} diff --git a/unit-tests/VMSizes-Must-Match-Template/Pass/Multiple-Nested-VMSizes/createUIDefinition.json b/unit-tests/VMSizes-Must-Match-Template/Pass/Multiple-Nested-VMSizes/createUIDefinition.json new file mode 100644 index 00000000..abb15d76 --- /dev/null +++ b/unit-tests/VMSizes-Must-Match-Template/Pass/Multiple-Nested-VMSizes/createUIDefinition.json @@ -0,0 +1,92 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/0.1.2-preview/CreateUIDefinition.MultiVm.json#", + "handler": "Microsoft.Azure.CreateUIDef", + "version": "0.1.2-preview", + "parameters": { + "basics": [], + "steps": [ + { + "label": "Scheduler", + "name": "scheduler", + "bladeTitle": "Scheduler", + "bladeSubtitle": "Configure Scheduler", + "elements": [ + { + "label": "Scheduler Section", + "name": "schedulerSection", + "type": "Microsoft.Common.Section", + "elements": [ + { + "label": "Scheduler VM Size", + "name": "vmsize", + "type": "Microsoft.Compute.SizeSelector", + "osPlatform": "Linux", + "count": 1, + "recommendedSizes": [ + "Standard_B1s" + ] + } + ] + }, + { + "label": "Login Nodes Section", + "name": "loginNodesSection", + "type": "Microsoft.Common.Section", + "elements": [ + { + "label": "Login Node VM Size", + "name": "vmsize", + "type": "Microsoft.Compute.SizeSelector", + "osPlatform": "Linux", + "count": 1, + "recommendedSizes": [ + "Standard_B1ms" + ] + } + ] + } + ] + }, + { + "label": "Slurm Settings", + "name": "slurmSettings", + "bladeTitle": "Slurm Settings", + "elements": [ + { + "label": "HTC Section", + "name": "HTCSection", + "type": "Microsoft.Common.Section", + "elements": [ + { + "label": "HTC VM Size", + "name": "vmsize", + "type": "Microsoft.Compute.SizeSelector", + "osPlatform": "Linux", + "count": 1, + "recommendedSizes": [ + "Standard_B2s" + ] + } + ] + } + ] + } + ], + "outputs": { + "location": "[location()]", + "clusters": { + "slurm": { + "schedulerNode": { + "sku": "[steps('scheduler').schedulerSection.vmsize]" + }, + "loginNodes": { + "sku": "[steps('scheduler').loginNodesSection.vmsize]" + }, + "htc": { + "sku": "[steps('slurmSettings').HTCSection.vmsize]" + } + } + } + } + } +} From 8a29cf96663822f167539bb5bf4f17e33c6f7921 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 22:10:38 +0000 Subject: [PATCH 4/5] Improve clarity of Find-OutputProperty function with better comments and parameter naming Co-authored-by: psah434 <114955590+psah434@users.noreply.github.com> --- .../VMSizes-Must-Match-Template.test.ps1 | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/arm-ttk/testcases/CreateUIDefinition/VMSizes-Must-Match-Template.test.ps1 b/arm-ttk/testcases/CreateUIDefinition/VMSizes-Must-Match-Template.test.ps1 index dc7df2ee..2b7aa9cd 100644 --- a/arm-ttk/testcases/CreateUIDefinition/VMSizes-Must-Match-Template.test.ps1 +++ b/arm-ttk/testcases/CreateUIDefinition/VMSizes-Must-Match-Template.test.ps1 @@ -22,6 +22,7 @@ $MainTemplateParameters #break # Helper function to recursively search for a pattern in nested objects +# Returns the top-level property name and the matching value when found function Find-OutputProperty { param( [Parameter(Mandatory=$true)] @@ -31,22 +32,24 @@ function Find-OutputProperty { [string]$Pattern, [Parameter(Mandatory=$false)] - [string]$PropertyName = $null + [string]$TopLevelPropertyName = $null ) foreach ($prop in $Object.psobject.properties) { - $currentName = if ($PropertyName) { $PropertyName } else { $prop.Name } + # Track the top-level property name for matching with template parameters + # This is the property name we'll use to look up in MainTemplateParameters + $topLevelName = if ($TopLevelPropertyName) { $TopLevelPropertyName } else { $prop.Name } if ($prop.Value -is [string] -and $prop.Value -like $Pattern) { - # Found a matching string value + # Found a matching string value - return the top-level property name return [PSCustomObject]@{ - Name = $currentName + Name = $topLevelName Value = $prop.Value } } elseif ($prop.Value -is [PSCustomObject] -or $prop.Value -is [System.Collections.Specialized.OrderedDictionary]) { - # Recursively search nested objects - $result = Find-OutputProperty -Object $prop.Value -Pattern $Pattern -PropertyName $currentName + # Recursively search nested objects, preserving the top-level property name + $result = Find-OutputProperty -Object $prop.Value -Pattern $Pattern -TopLevelPropertyName $topLevelName if ($result) { return $result } From 1616367b27711db92240363c12b57f41a24260b2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 22:12:12 +0000 Subject: [PATCH 5/5] Add comprehensive user scenario test case matching the reported issue Co-authored-by: psah434 <114955590+psah434@users.noreply.github.com> --- .../Pass/User-Scenario/azureDeploy.json | 9 ++ .../User-Scenario/createUIDefinition.json | 121 ++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 unit-tests/VMSizes-Must-Match-Template/Pass/User-Scenario/azureDeploy.json create mode 100644 unit-tests/VMSizes-Must-Match-Template/Pass/User-Scenario/createUIDefinition.json diff --git a/unit-tests/VMSizes-Must-Match-Template/Pass/User-Scenario/azureDeploy.json b/unit-tests/VMSizes-Must-Match-Template/Pass/User-Scenario/azureDeploy.json new file mode 100644 index 00000000..4ff94a8d --- /dev/null +++ b/unit-tests/VMSizes-Must-Match-Template/Pass/User-Scenario/azureDeploy.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "parameters": { + "clusters": { + "type": "object" + } + }, + "resources": [] +} diff --git a/unit-tests/VMSizes-Must-Match-Template/Pass/User-Scenario/createUIDefinition.json b/unit-tests/VMSizes-Must-Match-Template/Pass/User-Scenario/createUIDefinition.json new file mode 100644 index 00000000..cae68439 --- /dev/null +++ b/unit-tests/VMSizes-Must-Match-Template/Pass/User-Scenario/createUIDefinition.json @@ -0,0 +1,121 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/0.1.2-preview/CreateUIDefinition.MultiVm.json#", + "handler": "Microsoft.Azure.CreateUIDef", + "version": "0.1.2-preview", + "parameters": { + "basics": [], + "steps": [ + { + "label": "Scheduler", + "name": "scheduler", + "bladeTitle": "Scheduler Configuration", + "elements": [ + { + "label": "Scheduler Section", + "name": "schedulerSection", + "type": "Microsoft.Common.Section", + "elements": [ + { + "label": "Scheduler VM Size", + "name": "vmsize", + "type": "Microsoft.Compute.SizeSelector", + "osPlatform": "Linux", + "count": 1, + "recommendedSizes": ["Standard_D2s_v3"] + } + ] + }, + { + "label": "Login Nodes Section", + "name": "loginNodesSection", + "type": "Microsoft.Common.Section", + "elements": [ + { + "label": "Login Node VM Size", + "name": "vmsize", + "type": "Microsoft.Compute.SizeSelector", + "osPlatform": "Linux", + "count": 1, + "recommendedSizes": ["Standard_D2s_v3"] + } + ] + } + ] + }, + { + "label": "Slurm Settings", + "name": "slurmSettings", + "bladeTitle": "Slurm Configuration", + "elements": [ + { + "label": "HTC Section", + "name": "HTCSection", + "type": "Microsoft.Common.Section", + "elements": [ + { + "label": "HTC VM Size", + "name": "vmsize", + "type": "Microsoft.Compute.SizeSelector", + "osPlatform": "Linux", + "count": 1, + "recommendedSizes": ["Standard_F2s_v2"] + } + ] + }, + { + "label": "HPC Section", + "name": "HPCSection", + "type": "Microsoft.Common.Section", + "elements": [ + { + "label": "HPC VM Size", + "name": "vmsize", + "type": "Microsoft.Compute.SizeSelector", + "osPlatform": "Linux", + "count": 1, + "recommendedSizes": ["Standard_HC44rs"] + } + ] + }, + { + "label": "GPU Section", + "name": "GPUSection", + "type": "Microsoft.Common.Section", + "elements": [ + { + "label": "GPU VM Size", + "name": "vmsize", + "type": "Microsoft.Compute.SizeSelector", + "osPlatform": "Linux", + "count": 1, + "recommendedSizes": ["Standard_NC6"] + } + ] + } + ] + } + ], + "outputs": { + "location": "[location()]", + "clusters": { + "slurm": { + "schedulerNode": { + "sku": "[steps('scheduler').schedulerSection.vmsize]" + }, + "loginNodes": { + "sku": "[steps('scheduler').loginNodesSection.vmsize]" + }, + "htc": { + "sku": "[steps('slurmSettings').HTCSection.vmsize]" + }, + "hpc": { + "sku": "[steps('slurmSettings').HPCSection.vmsize]" + }, + "gpu": { + "sku": "[steps('slurmSettings').GPUSection.vmsize]" + } + } + } + } + } +}