aspire
aspire copied to clipboard
Add support for Azure Functions in Aspire
This work item tracks the work to support integrating .NET Azure Functions projects to the Aspire app model, support local development with debugging in VS and VS Code, and support deploying Azure Functions to ACA.
This only applies to the new v4 isolated workers and will not work for in process functions.
Local Development Experience
- [x] Ability to reference a .NET Azure Functions project in the app model as a project resource
- ~~[ ] Ability to reference a non-.NET azure functions project in the app model~~ (not target for 9.0 GA)
- [x] Ability to reference cloud resources and have them be picked up by functions (service bus, blobs etc)
- [x] Ability to use service discovery in a Functions worker app
- [ ] Ability to consume telemetry emitted from Azure Functions host from Aspire dashboard
- [x] Ability to debug Azure Functions projects in Aspire (Visual Studio)
- [ ] Ability to debug Azure Functions projects in Aspire (VS Code)
Deployment
- [x] Ability to deploy an Azure Functions app in Aspire to ACA (targeted for 9.0 GA)
- [ ] Ability to deploy an Azure Functions app in Aspire to Azure Functions (not targeted for 9.0 GA)
Original
Do you plan to integrate Aspire with Azure functions (I haven’t seen similar question in dotnet Conf nor samples and docs)?
Yes we plan to support functions as well, but it's not yet supported in the first preview.
cc @fabiocav
what's missing to support Aspire in Azure Functions v4 isolated? Would be nice to sketch out the required elements and identify which one are up for grabs, so we as a community can help. Thanks!
If the Aspire cloud deployment manifest tooling could automate the hosting & config of Azure Functions within Azure Container Apps (ACA) that would be fabulous. I need this but the protracted Dev/Ops guidance docs that describe how to host Azure functions within ACA have deterred me so far.
I added more details.
Also opened an issue and a new milestone in the .NET Worker repo to track the work happening there: https://github.com/Azure/azure-functions-dotnet-worker/issues/2090
I'm currently in the process of developing several local examples using Azure Functions with Aspire to better understand their capabilities and limitations. During this spike, I've encountered several issues and have a few questions. Could you please advise on the appropriate repository and process for reporting these issues and inquiries related to Azure Functions specifically with Aspire?
✅ - Ability to reference a .NET azure functions project in the app model ✅ - Ability to use service discovery in a function
I am able to spin it up locally, but am having trouble with getting rabbitmq consumer attribute parameter to work properly
And in the logs of the consumer I am seeing some connection issues, which I assume is just the function trying to connect to the container before it's actually up and running
link to repo: https://github.com/josephaw1022/AspireWithAzureFunctions
I have been trying to get something working locally also, and you are further than I am - but don't you need the ServiceDefaults added?
Without it, wouldn't it just be using your local.settings.json?
Edit: I just remembered. I had to modify the ServiceDefaults extensions to be able to apply it to the function app host builder. Here are my changes if it helps you at all: https://gist.github.com/sjasperse/2008cfcc4acee3ceeea7033a0e56af65
Site note: How is yours running? When I pull your repo and run it, my function app says "The gRPC channel URI 'http://:'/; could not be parsed." which is all the further I've gotten in my own experimenting also.
- This is good stuff! I was trying to figure out how exactly how do this and stuck on that piece with the service defaults. I can add that to my repo. I'm just doing it in my repo right now and then going to put a pr into the samples repo once I have something presentable lol. Just having issues with the sln building (and something with the csproj and needing to make a build.prop.targets) and just want to stay focused on getting the poc done first. But anyway, I am not sure what the issue is and why anything grpc is being mentioned? Can you send a screenshot of the terminal with the error? I am just running this via visual studio 2022 preview with the .net 8 and all that. And the service defaults method is just the method that you made. All it does is the metrics and services. It doesn't really have anything to do with configuration values.
I put my code in a repo for you. Basically just the Aspire Starter template, plus a templated function app (manually set to .NET 8). Here is a repo: https://github.com/sjasperse/AspireStarterWithFunctions/tree/master/AspireStarter.AppFunctions
Screenshot of the terminal output:
From what I can google, this sounds like an expected error when the function app is started like a regular .exe project, instead of using func start (which makes sense that it would expect the function runtime to be there) - so I'm confused how you have it working :-). I didn't really expect it to work, until I saw your screenshot and I started scratching my head.
Also - I'm on a Mac. Maybe that has something to do with it?
I put my code in a repo for you. Basically just the Aspire Starter template, plus a templated function app (manually set to .NET 8). Here is a repo: https://github.com/sjasperse/AspireStarterWithFunctions/tree/master/AspireStarter.AppFunctions
Screenshot of the terminal output:
From what I can google, this sounds like an expected error when the function app is started like a regular .exe project, instead of using
func start(which makes sense that it would expect the function runtime to be there) - so I'm confused how you have it working :-). I didn't really expect it to work, until I saw your screenshot and I started scratching my head.Also - I'm on a Mac. Maybe that has something to do with it?
I would remove the
tracing.AddAspNetCoreInstrumentation()
.AddGrpcClientInstrumentation()
.AddHttpClientInstrumentation();
from the extension method in service defaults.
Not an actual fix to the core issue, but might or might not fix the issue from occuring
I realized I never came back and replied to this. I removed those lines you suggested (good suggestion), and had the same result. I also tried your repo on my windows VM, and got the same gRPC error as on my mac.
I am still so confused how you got your function app to start up at all under Aspire. haha.
It does start, but service discovery doesn't work - this does:
var apiservice = builder.AddProject<Projects.AspireSample_FunctionApp>("apiservice");
builder.AddProject<Projects.AspireSample_Web>("webfrontend")
.WithReference(cache)
.WithReference("apiservice", new Uri("http://localhost:7071"));
The trick with @sjasperse's code is that there are overrides that use IHostBuilder instead of IHostApplicationBuilder.
This is my az func, and it seems to work fine - web app correctly gets weather:
[Function("weatherforecast")]
public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req)
{
_logger.LogInformation("C# HTTP trigger function processed a request.");
var summaries = new[]
{
"Hello From AzFunc", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
var response = req.CreateResponse(HttpStatusCode.OK);
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
await response.WriteAsJsonAsync(forecast);
return response;
}
Also, needed to make sure the client was using the right (az func) uri:
public class WeatherApiClient(HttpClient httpClient)
{
public async Task<WeatherForecast[]> GetWeatherAsync()
{
return await httpClient.GetFromJsonAsync<WeatherForecast[]>("/api/weatherforecast") ?? [];
}
}
Your azure function needs to wire up service discovery to the service collection for it to work.
If I am remembering what I did correctly, I did notice that the grpc issues is that this only happens in the .net aspire 8 sample project. If you go and create a .net aspire stand alone project in a seperate sln, then service discovery seems to work fine from what I remember looking into a few weeks ago in this repo.
I was able to get an example working here https://github.com/josephaw1022/AspireWithAzureFunctions/tree/master
But when I wrote this pr, I noticed the grpc issue that @sjasperse ran into https://github.com/dotnet/aspire-samples/pull/81
and that's when I started to think that it's not your device and something in the sln that is the root cause of this issue.
I also have the System.InvalidOperationException: The gRPC channel URI 'http://:'/; could not be parsed. exception when I am trying to run an azure function that it has a QueueTrigger.
@josephaw1022 In your repo, commenting out the AddProject of the QueueConsumer leads on the same error.
So is there any fix for that?
I found a temporary workaround to make azure functions work:
public static class Extensions
{
public static IResourceBuilder<ExecutableResource> AddAzureFunction<TServiceMetadata>(
this IDistributedApplicationBuilder builder,
string name,
int port,
int debugPort)
where TServiceMetadata : IServiceMetadata, new()
{
var serviceMetadata = new TServiceMetadata();
var projectPath = serviceMetadata.ProjectPath;
var projectDirectory = Path.GetDirectoryName(projectPath)!;
var args = new[]
{
"host",
"start",
"--port",
port.ToString(),
"--nodeDebugPort",
debugPort.ToString(),
"--pause-on-error"
};
return builder.AddResource(new ExecutableResource(name, "func", projectDirectory, args))
.WithOtlpExporter();
}
}
And then in Program.cs add the following
builder.AddAzureFunction<Projects.MyAzureFunction>(
"MyAzureFunction", port: 7074, debugPort: 5944);
@ChasakisD Good stuff!! One reservation that I have about it being in the sample project configured this way, is that if I'm remembering everything correctly, I do remember I was able to get azure functions working in an Aspire project as is. However, the issue has only occurred in the samples repo. And this fix that you came up with does work 👌🏻 (really good stuff, I have no idea how you came up with it), but it doesn't appear to be representative of how it would look running it normally.
Here is a link to the repo in which everything just works to better illustrate my point.
https://github.com/josephaw1022/AspireWithAzureFunctions
If the Aspire cloud deployment manifest tooling could automate the hosting & config of Azure Functions within Azure Container Apps (ACA) that would be fabulous.
Good news - this is on the horizon. We're working with our partners in Functions to prepare not only Functions support with Aspire, but also publishing of Functions to Azure Container Apps. I can't speak to a timeline today, but I'm aspiring to have this in your hands shortly after our GA of Aspire, as our priority is to give customers a fantastic end-to-end publishing experience to Azure Container Apps first. Publishing Functions to Container Apps is part of that story.
I was finally able to get a working function example going with @ChasakisD helpful extension method! I like it!.
https://github.com/sjasperse/AspireStarterWithFunctions/
It uses azurite as a queue mechanism, submits a message on each API request, with a correlation id, and then an isolated function app which uses middleware to create an OpenTelemetry trace with correlation id as the parent context (a little ugly how that's done, but it works). I couldn't figure out how to slip service discovery nicely into the function app, so I had to brute-force it a bit with the connection string environment variable.
Thanks! I tried @sjasperse 's project and using this container setting, I could use Volume, and set host port. Until official support, I would run Azure Function Project separate with AppHost, but it makes development possible. Edit : April 4 - also worked Function from AppHost. Needed to upgrade Azure Functions Core Tools inside my macOS.
In .NET Aspire preview 5 (8.0.0-preview.5.24201.12) the constructor signature of ExecutableResource has changed and the args are set via an extension method:
public static class Extensions
{
public static IResourceBuilder<ExecutableResource> AddAzureFunction<TProjectMetadata>(
this IDistributedApplicationBuilder builder,
string name,
int port,
int debugPort)
where TProjectMetadata : IProjectMetadata, new()
{
var projectMetadata = new TProjectMetadata();
var projectPath = projectMetadata.ProjectPath;
var projectDirectory = Path.GetDirectoryName(projectPath)!;
var args = new[]
{
"host",
"start",
"--port",
port.ToString(),
"--nodeDebugPort",
debugPort.ToString()
};
return builder.AddResource(new ExecutableResource(name, "func", projectDirectory))
.WithArgs(args)
.WithOtlpExporter();
}
}
I have some sample code here:
In .NET Aspire preview 5 (
8.0.0-preview.5.24201.12) the constructor signature ofExecutableResourcehas changed and the args are set via an extension method
There is also an AddExecutable extension method that takes care of the creation of the ExecutableResource.
Many thanks for the work done so far on this, while we wait for official support.
Our functions use self-generated certificates. For whatever reason, I can't get the --useHttps and --cert arguments to work via aspire, when passed in to AddExecutable(); I've tried all manner of relative and absolute paths to our .pfx file, but func host start ignores it, generates its own cert, which is then blocked by browsers. If I look at the final resolved command in the aspire dashboard, and just copy/paste it into a terminal, it works fine.
Has anyone got --cert working?
A question, but when deploy in azure, will be container app or azure function?
We're going to start with a container apps because it simplifies the networking requirements. Once we have that end to end working, then we'll explore deploying to functions compute.
Work has started on this here https://github.com/dotnet/aspire/pull/5418
Work has started on this here #5418
This PR has been merged and nightly builds of the new Aspire.Hosting.Azure.Functions package are now available. I made a sample repo with the integration over at https://github.com/captainsafia/AspireAzureFunctionsSample.
There's still a few kinks with the integration that require some changes in the Azure Functions Core Tools and Worker SDKs. The README of the repo above outlines some of the workarounds that need to applied for now in order to work around these issues. If you run into problems that aren't documented, let me know.
With the sample in the repo above, you should be able to:
- Use Azure Storage Queue, Azure Storage Blobs, and Azure Event Hubs as resources in your Functions project (support for more coming)
- Launch Functions projects in your Aspire App Host
- Debug Functions projects within Aspire in Visual Studio
Stay tuned for more work on this front!
Work has started on this here #5418
Thank very much!
If you need my help, I want to contribute to .NET ASPIRE
Will this also support all the dapr and container app related functionality in Aspire? So if I wanted to configure a dapr pubsub trigger in a function, I could run it locally?
