File: AzurePrivateDnsZoneResource.cs
Web Access
Project: src\src\Aspire.Hosting.Azure.Network\Aspire.Hosting.Azure.Network.csproj (Aspire.Hosting.Azure.Network)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using Azure.Core;
using Azure.Provisioning;
using Azure.Provisioning.Primitives;
using Azure.Provisioning.PrivateDns;
 
namespace Aspire.Hosting.Azure;
 
/// <summary>
/// Represents an Azure Private DNS Zone resource.
/// </summary>
internal sealed class AzurePrivateDnsZoneResource : AzureProvisioningResource
{
    /// <summary>
    /// Initializes a new instance of <see cref="AzurePrivateDnsZoneResource"/>.
    /// </summary>
    /// <param name="name">The Aspire resource name.</param>
    /// <param name="zoneName">The DNS zone name (e.g., "privatelink.blob.core.windows.net").</param>
    public AzurePrivateDnsZoneResource(string name, string zoneName)
        : base(name, ConfigureDnsZone)
    {
        ZoneName = zoneName;
    }
 
    /// <summary>
    /// Gets the DNS zone name (e.g., "privatelink.blob.core.windows.net").
    /// </summary>
    public string ZoneName { get; }
 
    /// <summary>
    /// Gets the "id" output reference from the Private DNS Zone resource.
    /// </summary>
    public BicepOutputReference Id => new("id", this);
 
    /// <summary>
    /// Gets the "name" output reference from the Private DNS Zone resource.
    /// </summary>
    public BicepOutputReference NameOutput => new("name", this);
 
    /// <summary>
    /// Tracks VNet Links for this DNS Zone, keyed by VNet resource.
    /// </summary>
    internal Dictionary<AzureVirtualNetworkResource, AzurePrivateDnsZoneVNetLinkResource> VNetLinks { get; } = [];
 
    /// <inheritdoc/>
    public override ProvisionableResource AddAsExistingResource(AzureResourceInfrastructure infra)
    {
        var bicepIdentifier = this.GetBicepIdentifier();
        var resources = infra.GetProvisionableResources();
 
        // Check if a PrivateDnsZone with the same identifier already exists
        var existingZone = resources.OfType<PrivateDnsZone>().SingleOrDefault(z => z.BicepIdentifier == bicepIdentifier);
 
        if (existingZone is not null)
        {
            return existingZone;
        }
 
        // Create and add new resource if it doesn't exist
        var dnsZone = PrivateDnsZone.FromExisting(bicepIdentifier);
 
        if (!TryApplyExistingResourceAnnotation(
            this,
            infra,
            dnsZone))
        {
            dnsZone.Name = NameOutput.AsProvisioningParameter(infra);
        }
 
        infra.Add(dnsZone);
        return dnsZone;
    }
 
    private static void ConfigureDnsZone(AzureResourceInfrastructure infra)
    {
        var resource = (AzurePrivateDnsZoneResource)infra.AspireResource;
 
        var dnsZone = new PrivateDnsZone(infra.AspireResource.GetBicepIdentifier())
        {
            Name = resource.ZoneName,
            Location = new AzureLocation("global"),
            Tags = { { "aspire-resource-name", resource.Name } }
        };
        infra.Add(dnsZone);
 
        // Create VNet Links for all linked VNets
        foreach (var vnetLinkEntry in resource.VNetLinks)
        {
            var vnetLink = vnetLinkEntry.Value;
            var linkIdentifier = Infrastructure.NormalizeBicepIdentifier($"{vnetLink.VNet.Name}_link");
 
            var link = new VirtualNetworkLink(linkIdentifier)
            {
                Name = $"{vnetLink.VNet.Name}-link",
                Parent = dnsZone,
                Location = new AzureLocation("global"),
                RegistrationEnabled = false,
                VirtualNetworkId = vnetLink.VNet.Id.AsProvisioningParameter(infra),
                Tags = { { "aspire-resource-name", vnetLink.Name } }
            };
            infra.Add(link);
        }
 
        // Output the DNS Zone ID for references
        infra.Add(new ProvisioningOutput("id", typeof(string))
        {
            Value = dnsZone.Id
        });
 
        infra.Add(new ProvisioningOutput("name", typeof(string))
        {
            Value = dnsZone.Name
        });
    }
}