File: AzureFrontDoorPrivateLinkTests.cs
Web Access
Project: src\tests\Aspire.Hosting.Azure.Tests\Aspire.Hosting.Azure.Tests.csproj (Aspire.Hosting.Azure.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
#pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates.
#pragma warning disable ASPIREACAEXPRESS001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
 
using Aspire.Hosting.ApplicationModel;
using Aspire.Hosting.Azure.AppContainers;
using Aspire.Hosting.Utils;
using Azure.Provisioning.Cdn;
using static Aspire.Hosting.Utils.AzureManifestUtils;
 
namespace Aspire.Hosting.Azure.Tests;
 
public class AzureFrontDoorPrivateLinkTests(ITestOutputHelper testOutputHelper)
{
    [Fact]
    public async Task WithAzureFrontDoorPrivateLinkConvertsOriginsToPrivateLinkOrigins()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, testOutputHelper);
 
        var environment = builder.AddAzureContainerAppEnvironment("env");
        var frontDoor = builder.AddAzureFrontDoor("frontdoor");
        environment.WithAzureFrontDoorPrivateLink(frontDoor);
 
        var api = builder.AddProject<Project>("api", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints();
        var web = builder.AddProject<Project>("web", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints();
        frontDoor.WithOrigin(api).WithOrigin(web);
 
        using var app = builder.Build();
 
        await ExecuteBeforeStartHooksAsync(app, default);
 
        var (_, bicep) = await GetManifestWithBicep(frontDoor.Resource);
 
        await Verify(bicep, "bicep");
    }
 
    [Fact]
    public async Task WithAzureFrontDoorPrivateLinkDisablesPublicNetworkAccessOnTheEnvironment()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, testOutputHelper);
 
        var environment = builder.AddAzureContainerAppEnvironment("env");
        var frontDoor = builder.AddAzureFrontDoor("frontdoor");
        environment.WithAzureFrontDoorPrivateLink(frontDoor);
 
        var api = builder.AddProject<Project>("api", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints();
        frontDoor.WithOrigin(api);
 
        using var app = builder.Build();
 
        await ExecuteBeforeStartHooksAsync(app, default);
 
        var (_, bicep) = await GetManifestWithBicep(environment.Resource);
 
        await Verify(bicep, "bicep");
    }
 
    [Fact]
    public async Task WithAzureFrontDoorPrivateLinkOrderDoesNotMatter()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, testOutputHelper);
 
        var api = builder.AddProject<Project>("api", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints();
        var frontDoor = builder.AddAzureFrontDoor("frontdoor")
            .WithOrigin(api);
        builder.AddAzureContainerAppEnvironment("env")
            .WithAzureFrontDoorPrivateLink(frontDoor);
 
        using var app = builder.Build();
 
        await ExecuteBeforeStartHooksAsync(app, default);
 
        var (_, bicep) = await GetManifestWithBicep(frontDoor.Resource);
 
        Assert.Contains("name: 'Premium_AzureFrontDoor'", bicep);
        Assert.Contains("groupId: 'managedEnvironments'", bicep);
    }
 
    [Fact]
    public async Task WithAzureFrontDoorPrivateLinkLocationCanBeOverriddenWithConfigureInfrastructure()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, testOutputHelper);
 
        var environment = builder.AddAzureContainerAppEnvironment("env");
        var publicEnvironment = builder.AddAzureContainerAppEnvironment("public-env");
        var privateLinkLocation = builder.AddParameter("privateLinkLocation");
        var frontDoor = builder.AddAzureFrontDoor("frontdoor")
            .ConfigureInfrastructure(infrastructure =>
            {
                var location = privateLinkLocation.AsProvisioningParameter(infrastructure);
                foreach (var origin in infrastructure.GetProvisionableResources().OfType<FrontDoorOrigin>())
                {
                    var privateLink = origin.SharedPrivateLinkResource;
                    if (!privateLink.PrivateLinkId.IsEmpty)
                    {
                        privateLink.PrivateLinkLocation = location;
                    }
                }
            });
        environment.WithAzureFrontDoorPrivateLink(frontDoor);
 
        var api = builder.AddProject<Project>("api", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints()
            .WithComputeEnvironment(environment);
        var publicApi = builder.AddProject<Project>("public-api", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints()
            .WithComputeEnvironment(publicEnvironment);
        frontDoor.WithOrigin(api).WithOrigin(publicApi);
 
        using var app = builder.Build();
 
        await ExecuteBeforeStartHooksAsync(app, default);
 
        var (_, bicep) = await GetManifestWithBicep(frontDoor.Resource);
 
        Assert.Equal(1, CountOccurrences(bicep, "sharedPrivateLinkResource:"));
        Assert.Equal(1, CountOccurrences(bicep, "privateLinkLocation: privateLinkLocation"));
        Assert.DoesNotContain("privateLinkLocation: env_location", bicep);
    }
 
    [Fact]
    public async Task WithAzureFrontDoorPrivateLinkKeepsSameEnvironmentReferencesOnIngressHosts()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, testOutputHelper);
 
        var environment = builder.AddAzureContainerAppEnvironment("env");
        var frontDoor = builder.AddAzureFrontDoor("frontdoor");
        environment.WithAzureFrontDoorPrivateLink(frontDoor);
 
        var api = builder.AddProject<Project>("api", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints();
        var web = builder.AddProject<Project>("web", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints()
            .WithReference(api)
            .WithEnvironment("API_HOST", api.GetEndpoint("https").Property(EndpointProperty.Host));
        frontDoor.WithOrigin(api).WithOrigin(web);
 
        using var app = builder.Build();
 
        await ExecuteBeforeStartHooksAsync(app, default);
 
        var (_, bicep) = await GetManifestWithBicep(GetContainerApp(web.Resource));
 
        await Verify(bicep, "bicep");
    }
 
    [Fact]
    public async Task WithAzureFrontDoorPrivateLinkLeavesOriginsInOtherEnvironmentsPublic()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, testOutputHelper);
 
        var privateEnvironment = builder.AddAzureContainerAppEnvironment("private-env");
        var publicEnvironment = builder.AddAzureContainerAppEnvironment("public-env");
        var frontDoor = builder.AddAzureFrontDoor("frontdoor");
        privateEnvironment.WithAzureFrontDoorPrivateLink(frontDoor);
 
        var privateApi = builder.AddProject<Project>("private-api", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints()
            .WithComputeEnvironment(privateEnvironment);
        var publicApi = builder.AddProject<Project>("public-api", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints()
            .WithComputeEnvironment(publicEnvironment);
        frontDoor.WithOrigin(privateApi).WithOrigin(publicApi);
 
        using var app = builder.Build();
 
        await ExecuteBeforeStartHooksAsync(app, default);
 
        var (_, frontDoorBicep) = await GetManifestWithBicep(frontDoor.Resource);
        var (_, publicEnvironmentBicep) = await GetManifestWithBicep(publicEnvironment.Resource);
 
        Assert.Equal(1, CountOccurrences(frontDoorBicep, "sharedPrivateLinkResource:"));
        Assert.DoesNotContain("publicNetworkAccess", publicEnvironmentBicep);
    }
 
    [Fact]
    public async Task WithAzureFrontDoorPrivateLinkConnectsEachFrontDoorToTheEnvironment()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, testOutputHelper);
 
        var environment = builder.AddAzureContainerAppEnvironment("env");
        var first = builder.AddAzureFrontDoor("first");
        var second = builder.AddAzureFrontDoor("second");
        environment.WithAzureFrontDoorPrivateLink(first).WithAzureFrontDoorPrivateLink(second);
 
        var api = builder.AddProject<Project>("api", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints();
        var web = builder.AddProject<Project>("web", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints();
        first.WithOrigin(api);
        second.WithOrigin(web);
 
        using var app = builder.Build();
 
        await ExecuteBeforeStartHooksAsync(app, default);
 
        var (_, firstBicep) = await GetManifestWithBicep(first.Resource);
        var (_, secondBicep) = await GetManifestWithBicep(second.Resource);
 
        Assert.Contains("requestMessage: 'Azure Front Door first requests access to env.'", firstBicep);
        Assert.Contains("requestMessage: 'Azure Front Door second requests access to env.'", secondBicep);
    }
 
    [Fact]
    public async Task WithAzureFrontDoorPrivateLinkConnectsOneFrontDoorToSeveralEnvironments()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, testOutputHelper);
 
        var west = builder.AddAzureContainerAppEnvironment("env-west");
        var east = builder.AddAzureContainerAppEnvironment("env-east");
        var frontDoor = builder.AddAzureFrontDoor("frontdoor");
        west.WithAzureFrontDoorPrivateLink(frontDoor);
        east.WithAzureFrontDoorPrivateLink(frontDoor);
 
        var api = builder.AddProject<Project>("api", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints()
            .WithComputeEnvironment(west);
        var admin = builder.AddProject<Project>("admin", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints()
            .WithComputeEnvironment(west);
        var web = builder.AddProject<Project>("web", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints()
            .WithComputeEnvironment(east);
        frontDoor.WithOrigin(api).WithOrigin(admin).WithOrigin(web);
 
        using var app = builder.Build();
 
        await ExecuteBeforeStartHooksAsync(app, default);
 
        var (_, bicep) = await GetManifestWithBicep(frontDoor.Resource);
 
        // Each environment has its own resource ID, region and request message, so Front Door creates one private
        // endpoint for each environment. The two origins in the same environment have the same settings, so they share one.
        await Verify(bicep, "bicep");
    }
 
    [Fact]
    public async Task WithAzureFrontDoorPrivateLinkThrowsWhenAnotherFrontDoorHasAnOriginInTheEnvironment()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, testOutputHelper);
 
        var environment = builder.AddAzureContainerAppEnvironment("env");
        var connected = builder.AddAzureFrontDoor("connected");
        var unconnected = builder.AddAzureFrontDoor("unconnected");
        environment.WithAzureFrontDoorPrivateLink(connected);
 
        var api = builder.AddProject<Project>("api", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints();
        var web = builder.AddProject<Project>("web", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints();
        connected.WithOrigin(api);
        unconnected.WithOrigin(web);
 
        using var app = builder.Build();
 
        var exception = await Assert.ThrowsAsync<InvalidOperationException>(() => ExecuteBeforeStartHooksAsync(app, default));
 
        Assert.Contains("Origin 'web' of Azure Front Door 'unconnected'", exception.ToString());
        Assert.Contains("WithAzureFrontDoorPrivateLink", exception.ToString());
    }
 
    [Fact]
    public async Task WithAzureFrontDoorPrivateLinkThrowsWhenNoOriginRunsInTheEnvironment()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, testOutputHelper);
 
        var privateEnvironment = builder.AddAzureContainerAppEnvironment("private-env");
        var publicEnvironment = builder.AddAzureContainerAppEnvironment("public-env");
        var frontDoor = builder.AddAzureFrontDoor("frontdoor");
        privateEnvironment.WithAzureFrontDoorPrivateLink(frontDoor);
 
        var api = builder.AddProject<Project>("api", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints()
            .WithComputeEnvironment(publicEnvironment);
        frontDoor.WithOrigin(api);
 
        using var app = builder.Build();
 
        var exception = await Assert.ThrowsAsync<InvalidOperationException>(() => ExecuteBeforeStartHooksAsync(app, default));
 
        Assert.Contains("none of its origins run in that environment", exception.ToString());
    }
 
    [Fact]
    public async Task WithAzureFrontDoorPrivateLinkThrowsForExpressEnvironments()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, testOutputHelper);
 
        var environment = builder.AddAzureContainerAppEnvironment("env").AsExpress();
        var frontDoor = builder.AddAzureFrontDoor("frontdoor");
        environment.WithAzureFrontDoorPrivateLink(frontDoor);
 
        var api = builder.AddProject<Project>("api", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints();
        frontDoor.WithOrigin(api);
 
        using var app = builder.Build();
 
        var exception = await Assert.ThrowsAsync<InvalidOperationException>(() => ExecuteBeforeStartHooksAsync(app, default));
 
        Assert.Contains("Express environment 'env' cannot be the target of a private link", exception.ToString());
    }
 
    [Fact]
    public async Task WithAzureFrontDoorPrivateLinkThrowsForExistingEnvironments()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, testOutputHelper);
 
        var environment = builder.AddAzureContainerAppEnvironment("env")
            .PublishAsExisting("existing-env", "existing-rg");
        var frontDoor = builder.AddAzureFrontDoor("frontdoor");
        environment.WithAzureFrontDoorPrivateLink(frontDoor);
 
        var api = builder.AddProject<Project>("api", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints();
        frontDoor.WithOrigin(api);
 
        using var app = builder.Build();
 
        var exception = await Assert.ThrowsAsync<InvalidOperationException>(() => ExecuteBeforeStartHooksAsync(app, default));
 
        Assert.Contains("is marked as existing but is also the target of a private link", exception.ToString());
    }
 
    [Fact]
    public void WithAzureFrontDoorPrivateLinkIsIdempotent()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, testOutputHelper);
 
        var environment = builder.AddAzureContainerAppEnvironment("env");
        var frontDoor = builder.AddAzureFrontDoor("frontdoor");
 
        environment.WithAzureFrontDoorPrivateLink(frontDoor);
        environment.WithAzureFrontDoorPrivateLink(frontDoor);
 
        Assert.Single(frontDoor.Resource.Annotations.OfType<AzureFrontDoorPrivateLinkAnnotation>());
        Assert.Single(environment.Resource.Annotations.OfType<PrivateEndpointTargetAnnotation>());
    }
 
    [Fact]
    public void WithAzureFrontDoorPrivateLinkDoesNothingInRunMode()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Run, testOutputHelper);
 
        var environment = builder.AddAzureContainerAppEnvironment("env");
        var frontDoor = builder.AddAzureFrontDoor("frontdoor");
 
        var result = environment.WithAzureFrontDoorPrivateLink(frontDoor);
 
        Assert.Same(environment, result);
        Assert.Empty(environment.Resource.Annotations.OfType<PrivateEndpointTargetAnnotation>());
        Assert.Empty(frontDoor.Resource.Annotations.OfType<AzureFrontDoorPrivateLinkAnnotation>());
    }
 
    [Fact]
    public void WithAzureFrontDoorPrivateLinkValidatesArguments()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, testOutputHelper);
 
        var environment = builder.AddAzureContainerAppEnvironment("env");
        var frontDoor = builder.AddAzureFrontDoor("frontdoor");
 
        Assert.Throws<ArgumentNullException>(() => ((IResourceBuilder<AzureContainerAppEnvironmentResource>)null!).WithAzureFrontDoorPrivateLink(frontDoor));
        Assert.Throws<ArgumentNullException>(() => environment.WithAzureFrontDoorPrivateLink(null!));
    }
 
    [Fact]
    public void RequestMessageStaysWithinTheFrontDoorLimit()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, testOutputHelper);
 
        var environment = builder.AddAzureContainerAppEnvironment(new string('e', 55));
        var frontDoor = builder.AddAzureFrontDoor(new string('f', 55));
        environment.WithAzureFrontDoorPrivateLink(frontDoor);
 
        var connection = Assert.Single(frontDoor.Resource.Annotations.OfType<AzureFrontDoorPrivateLinkAnnotation>());
 
        Assert.Equal(140, connection.RequestMessage.Length);
    }
 
    [Fact]
    public void RemappedRegionsPointToRegionsWithFrontDoorPrivateLink()
    {
        // The regions of https://learn.microsoft.com/azure/frontdoor/private-link#region-availability, normalized.
        string[] supportedRegions =
        [
            "brazilsouth", "canadacentral", "centralus", "eastus", "eastus2", "southcentralus", "westus2", "westus3",
            "usgovarizona", "usgovtexas", "usgovvirginia", "usnateast", "usnatwest", "usseceast", "ussecwest",
            "francecentral", "germanywestcentral", "northeurope", "norwayeast", "uksouth", "westeurope", "swedencentral",
            "southafricanorth", "uaenorth",
            "australiaeast", "centralindia", "japaneast", "koreacentral", "eastasia", "southeastasia", "chinaeast3", "chinanorth3"
        ];
 
        foreach (var (region, privateLinkRegion) in FrontDoorPrivateLinkRegions.Remapped)
        {
            Assert.Matches("^[a-z0-9]+$", region);
            Assert.DoesNotContain(region, supportedRegions);
            Assert.Contains(privateLinkRegion, supportedRegions);
        }
    }
 
    [Fact]
    public async Task WithAzureFrontDoorPrivateLinkDeclaresTheRegionMapOnce()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, testOutputHelper);
 
        var west = builder.AddAzureContainerAppEnvironment("west");
        var east = builder.AddAzureContainerAppEnvironment("east");
        var frontDoor = builder.AddAzureFrontDoor("frontdoor");
        west.WithAzureFrontDoorPrivateLink(frontDoor);
        east.WithAzureFrontDoorPrivateLink(frontDoor);
 
        var westApi = builder.AddProject<Project>("west-api", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints()
            .WithComputeEnvironment(west);
        var eastApi = builder.AddProject<Project>("east-api", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints()
            .WithComputeEnvironment(east);
        frontDoor.WithOrigin(westApi).WithOrigin(eastApi);
 
        using var app = builder.Build();
 
        await ExecuteBeforeStartHooksAsync(app, default);
 
        var (_, bicep) = await GetManifestWithBicep(frontDoor.Resource);
 
        Assert.Equal(1, CountOccurrences(bicep, "var privateLinkRegions = {"));
        Assert.Contains("privateLinkLocation: (privateLinkRegions[?west_location] ?? west_location)", bicep);
        Assert.Contains("privateLinkLocation: (privateLinkRegions[?east_location] ?? east_location)", bicep);
    }
 
    [Fact]
    public async Task WithAzureFrontDoorPrivateLinkSupportsAnyPrivateLinkTarget()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, testOutputHelper);
 
        var target = builder.AddResource(new TestPrivateLinkTarget("target"));
        var frontDoor = builder.AddAzureFrontDoor("frontdoor");
        target.WithAzureFrontDoorPrivateLink(frontDoor);
 
        var api = builder.AddProject<Project>("api", launchProfileName: null)
            .WithHttpsEndpoint()
            .WithExternalHttpEndpoints()
            .WithComputeEnvironment(target);
        frontDoor.WithOrigin(api);
 
        using var app = builder.Build();
 
        await ExecuteBeforeStartHooksAsync(app, default);
 
        var (_, bicep) = await GetManifestWithBicep(frontDoor.Resource);
 
        Assert.Contains("name: 'Premium_AzureFrontDoor'", bicep);
        Assert.Contains("id: target_environment_id", bicep);
        Assert.Contains("privateLinkLocation: (privateLinkRegions[?target_location] ?? target_location)", bicep);
        Assert.Contains("groupId: 'sites'", bicep);
        Assert.Contains("requestMessage: 'Azure Front Door frontdoor requests access to target.'", bicep);
        Assert.Single(target.Resource.Annotations.OfType<PrivateEndpointTargetAnnotation>());
    }
 
    [Fact]
    public void AzureContainerAppEnvironmentIsAPrivateLinkTarget()
    {
        var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, testOutputHelper);
 
        var environment = builder.AddAzureContainerAppEnvironment("env");
 
        var target = Assert.IsAssignableFrom<IAzureCdnPrivateLinkTarget>(environment.Resource);
        Assert.Equal("managedEnvironments", target.PrivateLinkGroupId);
        Assert.Equal("AZURE_CONTAINER_APPS_ENVIRONMENT_ID", target.Id.Name);
        Assert.Equal("AZURE_CONTAINER_APPS_ENVIRONMENT_LOCATION", target.Location.Name);
    }
 
    private static IResource GetContainerApp(IResource resource)
    {
        var target = resource.GetDeploymentTargetAnnotation();
        Assert.NotNull(target);
        return Assert.IsAssignableFrom<AzureProvisioningResource>(target.DeploymentTarget);
    }
 
    private static int CountOccurrences(string text, string value)
    {
        var count = 0;
        for (var index = text.IndexOf(value, StringComparison.Ordinal); index >= 0; index = text.IndexOf(value, index + value.Length, StringComparison.Ordinal))
        {
            count++;
        }
 
        return count;
    }
 
    private sealed class Project : IProjectMetadata
    {
        public string ProjectPath => "project";
    }
 
    // A compute environment other than Azure Container Apps that Front Door can reach over Private Link.
    private sealed class TestPrivateLinkTarget(string name)
        : AzureProvisioningResource(name, _ => { }), IAzureCdnPrivateLinkTarget
    {
        public BicepOutputReference Id => new("id", this);
 
        public BicepOutputReference Location => new("location", this);
 
        public string PrivateLinkGroupId => "sites";
 
        public ReferenceExpression GetHostAddressExpression(EndpointReference endpointReference)
            => ReferenceExpression.Create($"{endpointReference.Resource.Name}.{new BicepOutputReference("domain", this)}");
    }
}