Skip to content

Expose container app constants #8923

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
FullStackChef opened this issue Apr 23, 2025 · 9 comments
Open

Expose container app constants #8923

FullStackChef opened this issue Apr 23, 2025 · 9 comments
Labels
area-integrations Issues pertaining to Aspire Integrations packages azure Issues associated specifically with scenarios tied to using Azure

Comments

@FullStackChef
Copy link
Contributor

FullStackChef commented Apr 23, 2025

Background and Motivation

AddAzureContainerAppEnvironment outputs a number of provisioning parameters that can be referenced using their string names - these values can be useful within infrastructure provisioning; however it currently relies on using the string names.

Proposed API

Simply expos a constants object that includes the parameters exposed in AddAzureContainerAppEnvironment

infra.Add(new ProvisioningOutput("MANAGED_IDENTITY_NAME", typeof(string))
{
    Value = identity.Name
});

infra.Add(new ProvisioningOutput("MANAGED_IDENTITY_PRINCIPAL_ID", typeof(string))
{
    Value = identity.PrincipalId
});

infra.Add(new ProvisioningOutput("AZURE_LOG_ANALYTICS_WORKSPACE_NAME", typeof(string))
{
    Value = laWorkspace.Name
});

infra.Add(new ProvisioningOutput("AZURE_LOG_ANALYTICS_WORKSPACE_ID", typeof(string))
{
    Value = laWorkspace.Id
});

infra.Add(new ProvisioningOutput("AZURE_CONTAINER_REGISTRY_NAME", typeof(string))
{
    Value = containerRegistry.Name
});

infra.Add(new ProvisioningOutput("AZURE_CONTAINER_REGISTRY_ENDPOINT", typeof(string))
{
    Value = containerRegistry.LoginServer
});

infra.Add(new ProvisioningOutput("AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID", typeof(string))
{
    Value = identity.Id
});

infra.Add(new ProvisioningOutput("AZURE_CONTAINER_APPS_ENVIRONMENT_NAME", typeof(string))
{
    Value = containerAppEnvironment.Name
});

infra.Add(new ProvisioningOutput("AZURE_CONTAINER_APPS_ENVIRONMENT_ID", typeof(string))
{
    Value = containerAppEnvironment.Id
});

infra.Add(new ProvisioningOutput("AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN", typeof(string))
{
    Value = containerAppEnvironment.DefaultDomain
});
namespace Aspire.Hosting;

public class AzureContainerConstants
{
    public const string MANAGED_IDENTITY_NAME = nameof(MANAGED_IDENTITY_NAME);
    public const string MANAGED_IDENTITY_PRINCIPAL_ID = nameof(MANAGED_IDENTITY_PRINCIPAL_ID);
    public const string AZURE_LOG_ANALYTICS_WORKSPACE_NAME = nameof(AZURE_LOG_ANALYTICS_WORKSPACE_NAME);
    public const string AZURE_LOG_ANALYTICS_WORKSPACE_ID = nameof(AZURE_LOG_ANALYTICS_WORKSPACE_ID);
    public const string AZURE_CONTAINER_REGISTRY_NAME = nameof(AZURE_CONTAINER_REGISTRY_NAME);
    public const string AZURE_CONTAINER_REGISTRY_ENDPOINT = nameof(AZURE_CONTAINER_REGISTRY_ENDPOINT);
    public const string AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID = nameof(AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID);
    public const string AZURE_CONTAINER_APPS_ENVIRONMENT_NAME = nameof(AZURE_CONTAINER_APPS_ENVIRONMENT_NAME);
    public const string AZURE_CONTAINER_APPS_ENVIRONMENT_ID = nameof(AZURE_CONTAINER_APPS_ENVIRONMENT_ID);
    public const string AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN = nameof(AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN);

}

Usage Examples

            var acrImageRegistry = builder.Resources.OfType<ProvisioningOutput>().FirstOrDefault(_ => _.BicepIdentifier == AzureContainerConstants.AZURE_CONTAINER_REGISTRY_ENDPOINT);

Alternative Designs

Risks

@github-actions github-actions bot added the area-integrations Issues pertaining to Aspire Integrations packages label Apr 23, 2025
@davidfowl
Copy link
Member

We made these private until further notice. What are you using it for?

#8529

For now you can manually create a BicepOutputReference from it with right name.

@FullStackChef
Copy link
Contributor Author

I feel that the fact that these variables may change over time supports exposing them - yes, if you change it, it breaks my code but it breaks it loud and ugly - the type of breaking change that is easy to address vs what I currently have - as you say manually creating it with the right name means if you change them, my code still breaks but I'm left wondering why.

for reference - yes I have manually created the constants in my project - I'm using them for this:

 public static IResourceBuilder<AzureContainerRegistryResource> AddAzureContainerRegistry(this IDistributedApplicationBuilder builder, string name)
 {
     var registry = new AzureContainerRegistryResource(name, static infrastructure =>
     {
         var registryResource = (AzureContainerRegistryResource)infrastructure.AspireResource;
         var containerRegistry = new ContainerRegistryService(registryResource.GetBicepIdentifier())
         {
             Sku = new() { Name = ContainerRegistrySkuName.Basic },
         };
         infrastructure.Add(containerRegistry);
         infrastructure.Add(new ProvisioningOutput(AzureContainerConstants.AZURE_CONTAINER_REGISTRY_NAME, typeof(string))
         {
             Value = containerRegistry.Name
         });

         infrastructure.Add(new ProvisioningOutput(AzureContainerConstants.AZURE_CONTAINER_REGISTRY_ENDPOINT, typeof(string))
         {
             Value = containerRegistry.LoginServer
         });
     });

     return builder.AddResource(registry);
 }

 public static IResourceBuilder<AzureContainerAppEnvironmentResource> WithReference(this IResourceBuilder<AzureContainerAppEnvironmentResource> builder, IResourceBuilder<AzureContainerRegistryResource> registryBuilder)
 {
     var managedIdentity = builder.GetOutput(AzureContainerConstants.AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID);
     var roleDefinitionId = BicepFunction.GetSubscriptionResourceId("Microsoft.Authorization/roleDefinitions", ContainerRegistryBuiltInRole.AcrPull.ToString());

     registryBuilder.ConfigureInfrastructure(infrastructure =>
     {
         if (infrastructure.GetProvisionableResources().OfType<ContainerRegistryService>().FirstOrDefault() is { } containerRegistry)
         {
             var principalId = new ProvisioningParameter(AzureBicepResource.KnownParameters.PrincipalId, typeof(string));
             infrastructure.Add(principalId);

             var pullRa = containerRegistry.CreateRoleAssignment(ContainerRegistryBuiltInRole.AcrPull,
                 RoleManagementPrincipalType.ServicePrincipal, principalId, "test");
             pullRa.Name = BicepFunction.CreateGuid(containerRegistry.Id, principalId, pullRa.RoleDefinitionId);
             infrastructure.Add(pullRa);
         }

     }).WithParameter(AzureBicepResource.KnownParameters.PrincipalId, managedIdentity);

     builder.ConfigureInfrastructure(infrastructure =>
     {
         if (infrastructure.GetProvisionableResources().OfType<ContainerRegistryService>().FirstOrDefault() is { } containerRegistry)
         {
             if (infrastructure.GetProvisionableResources().OfType<RoleAssignment>().FirstOrDefault(_ =>
             {
                 return _.RoleDefinitionId.Value! == roleDefinitionId.Value!;
             }) is { } roleAssignment)
             {
                 infrastructure.Remove(roleAssignment);
             }
             infrastructure.Remove(containerRegistry);
         }
         var outputParameters = infrastructure.GetProvisionableResources().OfType<ProvisioningOutput>();
         if (outputParameters.FirstOrDefault(_ => _.BicepIdentifier == AzureContainerConstants.AZURE_CONTAINER_REGISTRY_NAME) is { } registryName)
         {
             infrastructure.Remove(registryName);
         }
         if (outputParameters.FirstOrDefault(_ => _.BicepIdentifier == AzureContainerConstants.AZURE_CONTAINER_REGISTRY_ENDPOINT) is { } registryEndpoint)
         {
             infrastructure.Remove(registryEndpoint);
         }
     });

     return builder;
 }

@davidfowl
Copy link
Member

Can you explain what you’re trying to do and why?

@FullStackChef
Copy link
Contributor Author

I'm decoupling my container registry from my container app environment because I want one registry but more than one environment (across multiple projects)

@davidfowl
Copy link
Member

I’d file an issue asking for that more directly

@FullStackChef
Copy link
Contributor Author

Ok

@davidfowl
Copy link
Member

I believe @captainsafia has plans to support associating an existing acr with the ACA resource. Seems like it fits in well

@FullStackChef
Copy link
Contributor Author

@FullStackChef TODO: rewrite issue to be more useful per suggestion

@davidfowl davidfowl added the azure Issues associated specifically with scenarios tied to using Azure label Apr 27, 2025
@captainsafia
Copy link
Member

I believe @captainsafia has plans to support associating an existing acr with the ACA resource. Seems like it fits in well

#9005 tracks this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-integrations Issues pertaining to Aspire Integrations packages azure Issues associated specifically with scenarios tied to using Azure
Projects
None yet
Development

No branches or pull requests

3 participants