Skip to content
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

Add more AsProvisioningParameter overloads #6583

Merged
merged 1 commit into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 62 additions & 11 deletions src/Aspire.Hosting.Azure/AzureProvisioningResourceExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,7 @@ public static ProvisioningParameter AsProvisioningParameter(this IResourceBuilde

infrastructure.AspireResource.Parameters[parameterName] = parameterResourceBuilder.Resource;

var parameter = infrastructure.GetParameters().FirstOrDefault(p => p.BicepIdentifier == parameterName);
if (parameter is null)
{
parameter = new ProvisioningParameter(parameterName, typeof(string))
{
IsSecure = parameterResourceBuilder.Resource.Secret
};
infrastructure.Add(parameter);
}

return parameter;
return GetOrAddParameter(infrastructure, parameterName, parameterResourceBuilder.Resource.Secret);
}

/// <summary>
Expand Down Expand Up @@ -112,10 +102,71 @@ public static ProvisioningParameter AsProvisioningParameter(this BicepOutputRefe

infrastructure.AspireResource.Parameters[parameterName] = outputReference;

return GetOrAddParameter(infrastructure, parameterName);
}

/// <summary>
/// Creates a new <see cref="ProvisioningParameter"/> in <paramref name="infrastructure"/>, or reuses an existing bicep parameter if one with
/// the same name already exists, that corresponds to <paramref name="endpointReference"/>.
/// </summary>
/// <param name="endpointReference">
/// The <see cref="EndpointReference"/> to use for the value of the <see cref="ProvisioningParameter"/>.
/// </param>
/// <param name="infrastructure">The <see cref="AzureResourceInfrastructure"/> that contains the <see cref="ProvisioningParameter"/>.</param>
/// <param name="parameterName">The name of the parameter to be assigned.</param>
/// <returns>
/// The corresponding <see cref="ProvisioningParameter"/> that was found or newly created.
/// </returns>
/// <remarks>
/// This is useful when assigning a <see cref="BicepValue"/> to the value of an Aspire <see cref="EndpointReference"/>.
/// </remarks>
public static ProvisioningParameter AsProvisioningParameter(this EndpointReference endpointReference, AzureResourceInfrastructure infrastructure, string parameterName)
{
ArgumentNullException.ThrowIfNull(endpointReference);
ArgumentNullException.ThrowIfNull(infrastructure);
ArgumentException.ThrowIfNullOrEmpty(parameterName);

infrastructure.AspireResource.Parameters[parameterName] = endpointReference;

return GetOrAddParameter(infrastructure, parameterName);
}

/// <summary>
/// Creates a new <see cref="ProvisioningParameter"/> in <paramref name="infrastructure"/>, or reuses an existing bicep parameter if one with
/// the same name already exists, that corresponds to <paramref name="expression"/>.
/// </summary>
/// <param name="expression">
/// The <see cref="ReferenceExpression"/> that represents the value to use for the <see cref="ProvisioningParameter"/>.
/// </param>
/// <param name="infrastructure">The <see cref="AzureResourceInfrastructure"/> that contains the <see cref="ProvisioningParameter"/>.</param>
/// <param name="parameterName">The name of the parameter to be assigned.</param>
/// <returns>
/// The corresponding <see cref="ProvisioningParameter"/> that was found or newly created.
/// </returns>
/// <remarks>
/// This is useful when assigning a <see cref="BicepValue"/> to the value of an Aspire <see cref="EndpointReference"/>.
/// </remarks>
public static ProvisioningParameter AsProvisioningParameter(this ReferenceExpression expression, AzureResourceInfrastructure infrastructure, string parameterName)
{
ArgumentNullException.ThrowIfNull(expression);
ArgumentNullException.ThrowIfNull(infrastructure);
ArgumentException.ThrowIfNullOrEmpty(parameterName);

infrastructure.AspireResource.Parameters[parameterName] = expression;

return GetOrAddParameter(infrastructure, parameterName);
}

private static ProvisioningParameter GetOrAddParameter(AzureResourceInfrastructure infrastructure, string parameterName, bool? isSecure = null)
{
var parameter = infrastructure.GetParameters().FirstOrDefault(p => p.BicepIdentifier == parameterName);
if (parameter is null)
{
parameter = new ProvisioningParameter(parameterName, typeof(string));
if (isSecure.HasValue)
{
parameter.IsSecure = isSecure.Value;
};
infrastructure.Add(parameter);
}

Expand Down
2 changes: 2 additions & 0 deletions src/Aspire.Hosting.Azure/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ override Aspire.Hosting.Azure.AzureProvisioningResource.GetBicepTemplateString()
static Aspire.Hosting.AzureBicepResourceExtensions.WithParameter<T>(this Aspire.Hosting.ApplicationModel.IResourceBuilder<T!>! builder, string! name, Aspire.Hosting.ApplicationModel.EndpointReference! value) -> Aspire.Hosting.ApplicationModel.IResourceBuilder<T!>!
static Aspire.Hosting.AzureBicepResourceExtensions.WithParameter<T>(this Aspire.Hosting.ApplicationModel.IResourceBuilder<T!>! builder, string! name, Aspire.Hosting.ApplicationModel.ReferenceExpression! value) -> Aspire.Hosting.ApplicationModel.IResourceBuilder<T!>!
static Aspire.Hosting.AzureProvisioningResourceExtensions.AddAzureInfrastructure(this Aspire.Hosting.IDistributedApplicationBuilder! builder, string! name, System.Action<Aspire.Hosting.Azure.AzureResourceInfrastructure!>! configureInfrastructure) -> Aspire.Hosting.ApplicationModel.IResourceBuilder<Aspire.Hosting.Azure.AzureProvisioningResource!>!
static Aspire.Hosting.AzureProvisioningResourceExtensions.AsProvisioningParameter(this Aspire.Hosting.ApplicationModel.EndpointReference! endpointReference, Aspire.Hosting.Azure.AzureResourceInfrastructure! infrastructure, string! parameterName) -> Azure.Provisioning.ProvisioningParameter!
static Aspire.Hosting.AzureProvisioningResourceExtensions.AsProvisioningParameter(this Aspire.Hosting.ApplicationModel.IResourceBuilder<Aspire.Hosting.ApplicationModel.ParameterResource!>! parameterResourceBuilder, Aspire.Hosting.Azure.AzureResourceInfrastructure! infrastructure, string? parameterName = null) -> Azure.Provisioning.ProvisioningParameter!
static Aspire.Hosting.AzureProvisioningResourceExtensions.AsProvisioningParameter(this Aspire.Hosting.ApplicationModel.ReferenceExpression! expression, Aspire.Hosting.Azure.AzureResourceInfrastructure! infrastructure, string! parameterName) -> Azure.Provisioning.ProvisioningParameter!
static Aspire.Hosting.AzureProvisioningResourceExtensions.AsProvisioningParameter(this Aspire.Hosting.Azure.BicepOutputReference! outputReference, Aspire.Hosting.Azure.AzureResourceInfrastructure! infrastructure, string? parameterName = null) -> Azure.Provisioning.ProvisioningParameter!
static Aspire.Hosting.AzureProvisioningResourceExtensions.ConfigureInfrastructure<T>(this Aspire.Hosting.ApplicationModel.IResourceBuilder<T!>! builder, System.Action<Aspire.Hosting.Azure.AzureResourceInfrastructure!>! configure) -> Aspire.Hosting.ApplicationModel.IResourceBuilder<T!>!
static Aspire.Hosting.AzureResourceExtensions.GetBicepIdentifier(this Aspire.Hosting.ApplicationModel.IAzureResource! resource) -> string!
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Aspire.Hosting.ApplicationModel;
using Aspire.Hosting.Utils;
using Azure.Provisioning.AppContainers;
using Xunit;
using Xunit.Abstractions;

namespace Aspire.Hosting.Azure.Tests;

public class AzureProvisioningResourceExtensionsTests(ITestOutputHelper output)
{
[Fact]
public async Task AsProvisioningParameterTests()
{
using var builder = TestDistributedApplicationBuilder.Create();

var apiProject = builder.AddProject<Project>("api", launchProfileName: null)
.WithHttpsEndpoint();

var endpointReference = apiProject.GetEndpoint("https");
var referenceExpression = ReferenceExpression.Create($"prefix:{endpointReference.Property(EndpointProperty.Host)}:{endpointReference.Property(EndpointProperty.Port)}");

var resource1 = builder.AddAzureInfrastructure("resource1", infrastructure =>
{
var endpointAddressParam = endpointReference.AsProvisioningParameter(infrastructure, parameterName: "endpointAddressParam");
var someExpressionParam = referenceExpression.AsProvisioningParameter(infrastructure, parameterName: "someExpressionParam");

var app = new ContainerApp("app");
app.Template.Scale.Rules =
[
new ContainerAppScaleRule()
{
Name = "temp",
Custom = new ContainerAppCustomScaleRule()
{
CustomScaleRuleType= "external",
Metadata =
{
{ "address", endpointAddressParam },
{ "someExpression", someExpressionParam },
}
}
}
];
infrastructure.Add(app);
});

var manifest = await ManifestUtils.GetManifestWithBicep(resource1.Resource);

var expectedManifest = """
{
"type": "azure.bicep.v0",
"path": "resource1.module.bicep",
"params": {
"endpointAddressParam": "{api.bindings.https.url}",
"someExpressionParam": "prefix:{api.bindings.https.host}:{api.bindings.https.port}"
}
}
""";
Assert.Equal(expectedManifest, manifest.ManifestNode.ToString());

var expectedBicep = """
@description('The location for the resource(s) to be deployed.')
param location string = resourceGroup().location

param endpointAddressParam string

param someExpressionParam string

resource app 'Microsoft.App/containerApps@2024-03-01' = {
name: take('app-${uniqueString(resourceGroup().id)}', 32)
location: location
properties: {
template: {
scale: {
rules: [
{
name: 'temp'
custom: {
type: 'external'
metadata: {
address: endpointAddressParam
someExpression: someExpressionParam
}
}
}
]
}
}
}
}
""";
output.WriteLine(manifest.BicepText);
Assert.Equal(expectedBicep, manifest.BicepText);
}

private sealed class Project : IProjectMetadata
{
public string ProjectPath => "project";
}
}
Loading