Skip to content

Add WithCompactResourceNaming() to fix storage name collisions#14442

Open
mitchdenny wants to merge 10 commits intorelease/13.2from
fix/compact-resource-naming-14427
Open

Add WithCompactResourceNaming() to fix storage name collisions#14442
mitchdenny wants to merge 10 commits intorelease/13.2from
fix/compact-resource-naming-14427

Conversation

@mitchdenny
Copy link
Member

Summary

Fixes #14427

When Azure Container App environment names are long (≥11 characters), the uniqueString suffix gets truncated in storage account and managed storage names, causing naming collisions across deployments in different resource groups.

Problem

Azure resource names are generated as take('{bicepIdentifier}{uniqueString(resourceGroup().id)}', maxLength). The uniqueString is 13 chars, and storage accounts have a 24-char max. Aspire's static suffixes (storageVolume = 13 chars, managedStorage = 14 chars) inflate the prefix, causing the unique suffix to be truncated or eliminated entirely.

Env Name Length Storage Account Name Unique Chars Preserved
5 chars myenvstoragevolume{uniq...} 6 of 13
8 chars myenvnmstoragevolume{un...} 3 of 13
11+ chars mylongenvstoragevolume{...} 0 — collision guaranteed

Solution

WithCompactResourceNaming() is an opt-in method that shortens only the length-constrained resource names while preserving the full 13-char uniqueString:

  • Storage accounts: take('{prefix}sv{resourceToken}', 24) — prefix truncated to 9 chars, 2-char marker, full 13-char token = 24
  • Managed storage: take('{name}-{volume}-{resourceToken}', 32) — includes both resource token (cross-deployment uniqueness) and volume name (within-deployment uniqueness)
  • File shares: take('{name}-{volume}', 60) — 63-char limit, less critical

Usage

var env = builder.AddAzureContainerAppEnvironment("myenv")
    .WithCompactResourceNaming();

Design Decisions

  • Opt-in only: Changing defaults would alter generated names and duplicate existing resources on upgrade
  • Targeted: Only changes storage account, managed storage, and file share names (not identity, ACR, log workspace, or CAE)
  • Azd precedence: If both WithAzdResourceNaming() and WithCompactResourceNaming() are used, Azd naming takes precedence (it already fixes storage)
  • Bicep identifiers unchanged: Variable names in generated bicep remain long/readable — only deployed .Name properties are shortened

Tests

  • 2 unit tests with snapshot verification (compact naming preserves uniqueString, multiple volumes have unique names)
  • 2 E2E deployment tests:
    • Deploy with long env name + compact naming + volume → verify storage account created successfully
    • Upgrade safety: GA CLI deploy → dev CLI upgrade → redeploy without compact naming → verify no duplicate storage accounts

@mitchdenny mitchdenny requested a review from eerhardt as a code owner February 11, 2026 06:25
Copilot AI review requested due to automatic review settings February 11, 2026 06:25
@github-actions
Copy link
Contributor

github-actions bot commented Feb 11, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 14442

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 14442"

@mitchdenny
Copy link
Member Author

/deployment-test

@github-actions
Copy link
Contributor

🚀 Deployment tests starting on PR #14442...

This will deploy to real Azure infrastructure. Results will be posted here when complete.

View workflow run

@github-actions github-actions bot temporarily deployed to deployment-testing February 11, 2026 06:31 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 11, 2026 06:31 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 11, 2026 06:31 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 11, 2026 06:31 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 11, 2026 06:31 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 11, 2026 06:31 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 11, 2026 06:31 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 11, 2026 06:31 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 11, 2026 06:31 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 11, 2026 06:31 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 11, 2026 06:31 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 11, 2026 06:31 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 11, 2026 06:31 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 11, 2026 06:31 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 11, 2026 06:31 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 11, 2026 06:31 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 11, 2026 06:31 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 11, 2026 06:31 Inactive
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an opt-in compact naming mode for Azure Container Apps environment–related storage resources to prevent storage account naming collisions when the environment name is long, while keeping the default naming behavior unchanged for upgrade safety.

Changes:

  • Add WithCompactResourceNaming() to generate shorter, collision-resistant names for storage account / managed storage / file shares.
  • Update Bicep generation to include a resourceToken when compact naming is enabled and apply new naming formulas.
  • Add unit snapshot tests and new E2E deployment/upgrade tests covering compact naming and upgrade safety.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Aspire.Hosting.Azure.AppContainers/AzureContainerAppExtensions.cs Implements compact naming logic and exposes WithCompactResourceNaming() API.
src/Aspire.Hosting.Azure.AppContainers/AzureContainerAppEnvironmentResource.cs Adds internal flag to enable compact naming behavior.
tests/Aspire.Hosting.Azure.Tests/AzureContainerAppsTests.cs Adds unit tests validating compact naming behavior via manifest/Bicep snapshots.
tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentWithCompactNamingPreservesUniqueString.verified.bicep Snapshot covering compact storage account naming for long env names.
tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentWithCompactNamingPreservesUniqueString.verified.json Snapshot metadata for the above test.
tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.CompactNamingMultipleVolumesHaveUniqueNames.verified.bicep Snapshot covering multiple volume/bind mount naming under compact mode.
tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.CompactNamingMultipleVolumesHaveUniqueNames.verified.json Snapshot metadata for the above test.
tests/Aspire.Deployment.EndToEnd.Tests/Helpers/DeploymentE2ETestHelpers.cs Adds helper to install GA/release-quality CLI for upgrade scenario testing.
tests/Aspire.Deployment.EndToEnd.Tests/AcaCompactNamingDeploymentTests.cs Adds E2E deployment test validating compact naming resolves collision scenario.
tests/Aspire.Deployment.EndToEnd.Tests/AcaCompactNamingUpgradeDeploymentTests.cs Adds E2E upgrade-safety test to ensure defaults don’t change across GA→dev upgrade.

Comment on lines +263 to +276
var volumeName = output.volume.Type switch
{
ContainerMountType.BindMount => $"bm{output.index}",
ContainerMountType.Volume => output.volume.Source ?? $"v{output.index}",
_ => throw new NotSupportedException()
};

// Remove '.' and '-' characters from volumeName
volumeName = volumeName.Replace(".", "").Replace("-", "");

share.Name = BicepFunction.Take(
BicepFunction.Interpolate(
$"{BicepFunction.ToLower(output.resource.Name)}-{BicepFunction.ToLower(volumeName)}"),
60);
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compact naming removes . and - from volumeName and then builds the file share name from only {resourceName}-{volumeName}. This can map distinct user-provided volume names to the same value (e.g., a-b vs ab, a.b vs ab), and there’s no output.index (or other discriminator) included to prevent collisions within the same storage account. Consider incorporating an invariant discriminator (like output.index) or using a collision-resistant normalization strategy.

Copilot uses AI. Check for mistakes.
Comment on lines +278 to +281
containerAppStorage.Name = BicepFunction.Take(
BicepFunction.Interpolate(
$"{BicepFunction.ToLower(output.resource.Name)}-{BicepFunction.ToLower(volumeName)}-{resourceToken}"),
32);
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

containerAppStorage.Name is built with take(..., 32). If output.resource.Name and/or volumeName are long, different volumes can collapse to the same 32-char prefix after truncation (the resourceToken suffix might also be truncated). To guarantee uniqueness within an environment, consider including an invariant short discriminator (e.g., output.index or a short hash) in the constructed name before applying take.

Copilot uses AI. Check for mistakes.
Comment on lines 179 to 186
sequenceBuilder
.Type("cp -f /tmp/aspire-cli-dev/aspire ~/.aspire/bin/aspire 2>/dev/null || echo 'Dev CLI not at /tmp, checking env...'")
.Enter()
.WaitForSuccessPrompt(counter);

// Re-source environment to pick up the dev CLI
sequenceBuilder.SourceAspireCliEnvironment(counter);
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In CI, restoring the dev CLI uses cp ... || echo ... and then proceeds without verifying the copy succeeded. If /tmp/aspire-cli-dev/aspire isn’t present (or the copy fails), the test may continue running the GA CLI and still pass, making the upgrade validation unreliable. Consider failing fast when the dev CLI artifact isn’t available and/or asserting after aspire --version that the expected (dev) build is running before redeploying.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Contributor

github-actions bot commented Feb 11, 2026

🎬 CLI E2E Test Recordings

The following terminal recordings are available for commit 471f184:

Test Recording
AgentCommands_AllHelpOutputs_AreCorrect ▶️ View Recording
AgentInitCommand_MigratesDeprecatedConfig ▶️ View Recording
Banner_DisplayedOnFirstRun ▶️ View Recording
Banner_DisplayedWithExplicitFlag ▶️ View Recording
CreateAndDeployToDockerCompose ▶️ View Recording
CreateAndDeployToDockerComposeInteractive ▶️ View Recording
CreateAndPublishToKubernetes ▶️ View Recording
CreateAndRunAspireStarterProject ▶️ View Recording
CreateAndRunAspireStarterProjectWithBundle ▶️ View Recording
CreateAndRunJsReactProject ▶️ View Recording
CreateAndRunPythonReactProject ▶️ View Recording
CreateEmptyAppHostProject ▶️ View Recording
CreateStartAndStopAspireProject ▶️ View Recording
CreateStartWaitAndStopAspireProject ▶️ View Recording
CreateTypeScriptAppHostWithViteApp ▶️ View Recording
DoctorCommand_DetectsDeprecatedAgentConfig ▶️ View Recording
DoctorCommand_WithSslCertDir_ShowsTrusted ▶️ View Recording
DoctorCommand_WithoutSslCertDir_ShowsPartiallyTrusted ▶️ View Recording
LogsCommandShowsResourceLogs ▶️ View Recording
PsCommandListsRunningAppHost ▶️ View Recording
ResourcesCommandShowsRunningResources ▶️ View Recording

📹 Recordings uploaded automatically from CI run #21940203098

@mitchdenny
Copy link
Member Author

/deployment-test

Mitch Denny added 4 commits February 12, 2026 20:06
…date

aspire update shows two prompts when switching channels:
1. 'Perform updates? [y/n]' - package confirmation
2. 'Which directory for NuGet.config file?' - NuGet config placement
Both need Enter to accept defaults.
aspire update has multiple sequential prompts (confirm, NuGet.config dir,
NuGet.config apply, potential CLI self-update). Use Wait+Enter pattern
to accept all defaults without needing to track each prompt individually.
Timed Enter presses were unreliable — if prompts appeared at different
speeds, extra Enters would leak to the shell and corrupt subsequent
commands. Now explicitly waits for each of the 3 prompts:
1. 'Perform updates? [y/n]'
2. 'Which directory for NuGet.config file?'
3. 'Apply these changes to NuGet.config? [y/n]'
@mitchdenny mitchdenny force-pushed the fix/compact-resource-naming-14427 branch from 3d7d38b to 471f184 Compare February 12, 2026 09:06
@mitchdenny
Copy link
Member Author

/deployment-test

@github-actions
Copy link
Contributor

🚀 Deployment tests starting on PR #14442...

This will deploy to real Azure infrastructure. Results will be posted here when complete.

View workflow run

@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions github-actions bot temporarily deployed to deployment-testing February 12, 2026 09:14 Inactive
@github-actions
Copy link
Contributor

Deployment E2E Tests passed

Summary: 21 passed, 0 failed, 0 cancelled

View workflow run

Passed Tests

  • ✅ AppServicePythonDeploymentTests
  • ✅ AksStarterWithRedisDeploymentTests
  • ✅ AcaCompactNamingUpgradeDeploymentTests
  • ✅ AzureLogAnalyticsDeploymentTests
  • ✅ AppServiceReactDeploymentTests
  • ✅ AzureAppConfigDeploymentTests
  • ✅ AcaCompactNamingDeploymentTests
  • ✅ AzureStorageDeploymentTests
  • ✅ AuthenticationTests
  • ✅ AzureKeyVaultDeploymentTests
  • ✅ AzureContainerRegistryDeploymentTests
  • ✅ VnetKeyVaultConnectivityDeploymentTests
  • ✅ AzureEventHubsDeploymentTests
  • ✅ VnetSqlServerInfraDeploymentTests
  • ✅ PythonFastApiDeploymentTests
  • ✅ AksStarterDeploymentTests
  • ✅ VnetStorageBlobConnectivityDeploymentTests
  • ✅ VnetStorageBlobInfraDeploymentTests
  • ✅ VnetKeyVaultInfraDeploymentTests
  • ✅ AcaStarterDeploymentTests
  • ✅ AzureServiceBusDeploymentTests

🎬 Terminal Recordings

Test Recording
DeployAzureAppConfigResource ▶️ View Recording
DeployAzureContainerRegistryResource ▶️ View Recording
DeployAzureEventHubsResource ▶️ View Recording
DeployAzureKeyVaultResource ▶️ View Recording
DeployAzureLogAnalyticsResource ▶️ View Recording
DeployAzureServiceBusResource ▶️ View Recording
DeployAzureStorageResource ▶️ View Recording
DeployPythonFastApiTemplateToAzureAppService ▶️ View Recording
DeployPythonFastApiTemplateToAzureContainerApps ▶️ View Recording
DeployReactTemplateToAzureAppService ▶️ View Recording
DeployStarterTemplateToAks ▶️ View Recording
DeployStarterTemplateToAzureContainerApps ▶️ View Recording
DeployStarterTemplateWithKeyVaultPrivateEndpoint ▶️ View Recording
DeployStarterTemplateWithRedisToAks ▶️ View Recording
DeployStarterTemplateWithStorageBlobPrivateEndpoint ▶️ View Recording
DeployVnetKeyVaultInfrastructure ▶️ View Recording
DeployVnetSqlServerInfrastructure ▶️ View Recording
DeployVnetStorageBlobInfrastructure ▶️ View Recording
DeployWithCompactNamingFixesStorageCollision ▶️ View Recording
UpgradeFromGaToDevDoesNotDuplicateStorageAccounts ▶️ View Recording

@mitchdenny mitchdenny added this to the 13.2 milestone Feb 12, 2026
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.

[AzureContainerAppEnvironment] Azure resource name contains too many static characters

2 participants