Summary
The current BlobClient in cli/azd/pkg/azsdk/storage/ is architecturally unique compared to other Azure service clients in the codebase. It binds the subscription/tenant at construction time via AccountConfig, whereas all other services (KeyVault, ContainerApps, ContainerRegistry, AppService, etc.) accept subscriptionId per-call and store only a SubscriptionCredentialProvider.
Current pattern (BlobClient — exception)
// Constructor locks in subscription via AccountConfig
func NewBlobSdkClient(credentialProvider, accountConfig *AccountConfig, ...) (*azblob.Client, error)
// Methods have no subscription parameter
type BlobClient interface {
Download(ctx context.Context, blobPath string) (io.ReadCloser, error)
Upload(ctx context.Context, blobPath string, reader io.Reader) error
// ...
}
Standard pattern (KeyVault, ContainerApps, etc.)
// Constructor takes credential provider only
func NewKeyVaultService(credentialProvider, ...) KeyVaultService
// Methods accept subscriptionId per-call
GetKeyVault(ctx, subscriptionId, resourceGroup, vaultName) (*KeyVault, error)
Interestingly, FileShareService in the same storage package already follows the standard per-call pattern.
Proposal
Refactor the blob storage abstraction into a StorageBlobService that:
- Follows the per-call
subscriptionId pattern used by other Azure services
- Stores a
SubscriptionCredentialProvider rather than pre-resolved credentials
- Can be consumed by the remote state feature (and any future blob storage consumers) without being locked to a single subscription at construction time
This is a code & design improvement — the current implementation works correctly for its single use case (remote state), but consolidating the pattern improves consistency and future extensibility.
Summary
The current
BlobClientincli/azd/pkg/azsdk/storage/is architecturally unique compared to other Azure service clients in the codebase. It binds the subscription/tenant at construction time viaAccountConfig, whereas all other services (KeyVault, ContainerApps, ContainerRegistry, AppService, etc.) acceptsubscriptionIdper-call and store only aSubscriptionCredentialProvider.Current pattern (BlobClient — exception)
Standard pattern (KeyVault, ContainerApps, etc.)
Interestingly,
FileShareServicein the same storage package already follows the standard per-call pattern.Proposal
Refactor the blob storage abstraction into a
StorageBlobServicethat:subscriptionIdpattern used by other Azure servicesSubscriptionCredentialProviderrather than pre-resolved credentialsThis is a code & design improvement — the current implementation works correctly for its single use case (remote state), but consolidating the pattern improves consistency and future extensibility.