Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 13, 2026

Users were selecting regions where project services aren't available, causing provision failures (e.g., Static Web Apps unavailable in France Central).

Implementation

Resource Type Extraction (pkg/azure/arm_template.go)

  • Parse compiled ARM templates to extract resource types from resources[] array
  • Returns deduplicated list like ["Microsoft.App/containerApps", "Microsoft.DBforPostgreSQL/flexibleServers"]

Provider Availability Check (pkg/account/subscriptions.go)

  • Query Azure Provider APIs per location to verify resource type registration and availability
  • Filter locations to those supporting ALL required resource types
  • Best-effort with error logging - API failures don't block user

Integration (pkg/infra/provisioning/bicep/)

  • Extract resource types during EnsureEnv() after Bicep compilation
  • Pass to location prompt via new PromptLocationWithResourceTypes() method
  • Works alongside existing allowedValues and quota filtering

Interface Extensions

  • Manager.GetLocationsWithFilter(resourceTypes []string) - filtered location retrieval
  • Prompter.PromptLocationWithResourceTypes(resourceTypes []string) - filtered prompting
  • EnsureSubscriptionAndLocationOptions.ResourceTypes - provisioning options

Example

Project using Container Apps + PostgreSQL:

// Bicep compiles to ARM template
resourceTypes := azure.ExtractResourceTypes(armTemplate)
// ["Microsoft.App/containerApps", "Microsoft.DBforPostgreSQL/flexibleServers"]

// Only ~30 compatible locations shown instead of 60+ total
locations := manager.GetLocationsWithFilter(ctx, subId, resourceTypes)

Notes

  • Backward compatible: when resourceTypes is nil/empty, no filtering occurs
  • Bicepparam mode skipped (requires subscription/location before compilation)
  • Invalid resource types logged and skipped
  • Provider API errors logged but don't fail operation

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • code.cloudfoundry.org
    • Triggering command: /update-job-proxy /update-job-proxy DROP bin/bash test -e cef98f5.0 /opt/hostedtoolc-e /bin/test rvice-availabili/usr/bin/git -buildtags /home/REDACTED/.do--global test -e oot_CA_2022.pem git est 1db302536c17e6f4/usr/sbin/iptables les ache/go/1.25.5/x-t test (dns block)
  • dario.cat
    • Triggering command: /update-job-proxy /update-job-proxy DROP bin/bash test -e cef98f5.0 /opt/hostedtoolc-e /bin/test rvice-availabili/usr/bin/git -buildtags /home/REDACTED/.do--global test -e oot_CA_2022.pem git est 1db302536c17e6f4/usr/sbin/iptables les ache/go/1.25.5/x-t test (dns block)
  • go.googlesource.com
    • Triggering command: /update-job-proxy /update-job-proxy DROP bin/bash test -e cef98f5.0 /opt/hostedtoolc-e /bin/test rvice-availabili/usr/bin/git -buildtags /home/REDACTED/.do--global test -e oot_CA_2022.pem git est 1db302536c17e6f4/usr/sbin/iptables les ache/go/1.25.5/x-t test (dns block)
  • go.opentelemetry.io
    • Triggering command: /update-job-proxy /update-job-proxy DROP bin/bash test -e cef98f5.0 /opt/hostedtoolc-e /bin/test rvice-availabili/usr/bin/git -buildtags /home/REDACTED/.do--global test -e oot_CA_2022.pem git est 1db302536c17e6f4/usr/sbin/iptables les ache/go/1.25.5/x-t test (dns block)
  • go.uber.org
    • Triggering command: /update-job-proxy /update-job-proxy DROP bin/bash test -e cef98f5.0 /opt/hostedtoolc-e /bin/test rvice-availabili/usr/bin/git -buildtags /home/REDACTED/.do--global test -e oot_CA_2022.pem git est 1db302536c17e6f4/usr/sbin/iptables les ache/go/1.25.5/x-t test (dns block)
  • google.golang.org
    • Triggering command: /update-job-proxy /update-job-proxy DROP bin/bash test -e cef98f5.0 /opt/hostedtoolc-e /bin/test rvice-availabili/usr/bin/git -buildtags /home/REDACTED/.do--global test -e oot_CA_2022.pem git est 1db302536c17e6f4/usr/sbin/iptables les ache/go/1.25.5/x-t test (dns block)
  • gopkg.in
    • Triggering command: /update-job-proxy /update-job-proxy DROP bin/bash test -e cef98f5.0 /opt/hostedtoolc-e /bin/test rvice-availabili/usr/bin/git -buildtags /home/REDACTED/.do--global test -e oot_CA_2022.pem git est 1db302536c17e6f4/usr/sbin/iptables les ache/go/1.25.5/x-t test (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Filter Region list by provider/service availability being used in project</issue_title>
<issue_description>Findings are showing that there are unsuccessful provision attempts due to services/providers not available in the region selected for a service that is in the project.

We are already filtering the available regions by subscription, we can add the services in the project as an additional filter to further reduce the list.

There are some of the templates that attempt to do this via the allowed parameter in the bicep files, but this is a manual list and has room for error.

Proposed solution -

Extend Existing Method with Optional Filtering
A backwards-compatible approach would be to add optional parameters:

// ...existing code...

// LocationFilterOptions provides filtering options for location queries
type LocationFilterOptions struct {
    ResourceProviders []string // Filter by resource provider availability
    ServiceTypes      []string // Filter by specific service types
    SkipQuotaCheck    bool     // Skip quota availability checks
}

// ListSubscriptionLocationsWithFilter lists physical locations with optional filtering
func (s *SubscriptionsService) ListSubscriptionLocationsWithFilter(
    ctx context.Context, 
    subscriptionId string, 
    tenantId string,
    options *LocationFilterOptions,
) ([]Location, error) {
    client, err := s.createSubscriptionsClient(ctx, tenantId)
    if err != nil {
        return nil, err
    }

    locations := []Location{}
    pager := client.NewListLocationsPager(subscriptionId, nil)

    for pager.More() {
        page, err := pager.NextPage(ctx)
        if err != nil {
            return nil, fmt.Errorf("failed getting next page of locations: %w", err)
        }

        for _, location := range page.LocationListResult.Value {
            // Only include physical locations
            if *location.Metadata.RegionType == "Physical" &&
                !compare.PtrValueEquals(location.Metadata.PhysicalLocation, "") {
                
                locationName := *location.Name
                
                // Apply filters if specified
                if options != nil {
                    if len(options.ResourceProviders) > 0 {
                        supported, err := s.checkProviderAvailability(ctx, subscriptionId, tenantId, locationName, options.ResourceProviders)
                        if err != nil || !supported {
                            continue
                        }
                    }
                    
                    if len(options.ServiceTypes) > 0 {
                        supported, err := s.checkServiceAvailability(ctx, subscriptionId, tenantId, locationName, options.ServiceTypes)
                        if err != nil || !supported {
                            continue
                        }
                    }
                }

                displayName := convert.ToValueWithDefault(location.DisplayName, locationName)
                regionalDisplayName := convert.ToValueWithDefault(location.RegionalDisplayName, displayName)

                locations = append(locations, Location{
                    Name:                locationName,
                    DisplayName:         displayName,
                    RegionalDisplayName: regionalDisplayName,
                })
            }
        }
    }

    sort.Slice(locations, func(i, j int) bool {
        return locations[i].RegionalDisplayName < locations[j].RegionalDisplayName
    })

    return locations, nil
}

Integration with Existing Prompt System
You would also need to update the prompt system to use the filtered locations. This would involve modifying pkg/azureutil/location.go

// Add new function that accepts service filters
func PromptLocationWithServiceFilter(
    ctx context.Context,
    subscriptionId string,
    message string,
    help string,
    console input.Console,
    accountManager account.Manager,
    shouldDisplay func(account.Location) bool,
    defaultSelectedLocation *string,
    serviceTypes []string, // New parameter for service filtering
) (string, error) {
    // Get filtered locations instead of all locations
    allLocations, err := accountManager.GetLocationsForServices(ctx, subscriptionId, serviceTypes)
    if err != nil {
        return "", fmt.Errorf("listing locations: %w", err)
    }

    // Rest of the function remains the same...
}

We would have to parse the bicep files for the services.</issue_description>

Comments on the Issue (you are @copilot in this section)

@weikanglim @spboyer Do you have a couple of a quick examples in mind?

I suspect what this ends up looking, in the case of a single location being used across multiple resources, could look like:

@metadata{
  azd:{
    // these resources use this same location variable
    resour...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes Azure/azure-dev#5424

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

Copilot AI and others added 4 commits January 13, 2026 16:18
Co-authored-by: spboyer <7681382+spboyer@users.noreply.github.com>
Co-authored-by: spboyer <7681382+spboyer@users.noreply.github.com>
Co-authored-by: spboyer <7681382+spboyer@users.noreply.github.com>
Co-authored-by: spboyer <7681382+spboyer@users.noreply.github.com>
Copilot AI changed the title [WIP] Filter region list by service availability in project Filter location prompts by resource provider availability Jan 13, 2026
Copilot AI requested a review from spboyer January 13, 2026 16:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants