Skip to content
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
3 changes: 3 additions & 0 deletions playground/FoundryAgents/FoundryAgents.AppHost/AppHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

var builder = DistributedApplication.CreateBuilder(args);

var aca = builder.AddAzureContainerAppEnvironment("env");

var foundry = builder.AddFoundry("aif-myfoundry");
var project = foundry.AddProject("proj-myproject")
// workaround for https://github.com/microsoft/aspire/issues/15971
Expand Down Expand Up @@ -71,6 +73,7 @@ create funny charts or calculations about the topic.

builder.AddProject<Projects.PromptAgentChat>("chat-app")
.WithExternalHttpEndpoints()
.WithComputeEnvironment(aca)
.WithReference(jokerAgent).WaitFor(jokerAgent)
.WithReference(researchAgent).WaitFor(researchAgent);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

<ItemGroup>
<AspireProjectOrPackageReference Include="Aspire.Hosting.Azure" />
<AspireProjectOrPackageReference Include="Aspire.Hosting.Azure.AppContainers" />
<AspireProjectOrPackageReference Include="Aspire.Hosting.Azure.Search" />
<AspireProjectOrPackageReference Include="Aspire.Hosting.Foundry" />
<AspireProjectOrPackageReference Include="Aspire.Hosting.AppHost" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public AzureContainerAppEnvironmentResource(string name, Action<AzureResourceInf
Name = $"prepare-azure-container-apps-{name}",
Description = $"Prepares Azure Container Apps deployment targets for {name}.",
Action = ctx => PrepareDeploymentTargetsAsync(ctx),
DependsOnSteps = [AzureEnvironmentResource.PrepareResourcesStepName],
DependsOnSteps = [AzureEnvironmentResource.PrepareResourcesStepName, WellKnownPipelineSteps.ValidateComputeEnvironments],
RequiredBySteps = [WellKnownPipelineSteps.BeforeStart]
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public AzureAppServiceEnvironmentResource(string name, Action<AzureResourceInfra
Name = $"prepare-azure-app-service-{name}",
Description = $"Prepares Azure App Service deployment targets for {name}.",
Action = ctx => PrepareDeploymentTargetsAsync(ctx),
DependsOnSteps = [AzureEnvironmentResource.PrepareResourcesStepName],
DependsOnSteps = [AzureEnvironmentResource.PrepareResourcesStepName, WellKnownPipelineSteps.ValidateComputeEnvironments],
RequiredBySteps = [WellKnownPipelineSteps.BeforeStart]
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public AzureKubernetesEnvironmentResource(
Name = $"prepare-aks-{Name}",
Description = $"Prepares Azure Kubernetes Service environment {Name}.",
Action = ctx => PrepareAksEnvironmentAsync(ctx),
DependsOnSteps = [WellKnownPipelineSteps.ValidateComputeEnvironments],
RequiredBySteps =
[
WellKnownPipelineSteps.BeforeStart,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public DockerComposeEnvironmentResource(string name) : base(name)
Name = $"prepare-deployment-targets-{Name}",
Description = $"Prepares Docker Compose deployment targets for {Name}.",
Action = ctx => PrepareDeploymentTargetsAsync(ctx),
DependsOnSteps = [WellKnownPipelineSteps.ValidateComputeEnvironments],
RequiredBySteps = [WellKnownPipelineSteps.BeforeStart]
};
steps.Add(prepareDeploymentTargetsStep);
Expand Down Expand Up @@ -118,7 +119,8 @@ public DockerComposeEnvironmentResource(string name) : base(name)
{
Name = $"prepare-{Name}",
Description = $"Prepares the Docker Compose environment {Name} for deployment.",
Action = ctx => PrepareAsync(ctx)
Action = ctx => PrepareAsync(ctx),
DependsOnSteps = [WellKnownPipelineSteps.ValidateComputeEnvironments]
};
prepareStep.DependsOn(WellKnownPipelineSteps.Publish);
prepareStep.DependsOn(WellKnownPipelineSteps.Build);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace Aspire.Hosting.Foundry;
/// <summary>
/// A Microsoft Foundry hosted agent resource.
/// </summary>
public class AzureHostedAgentResource : Resource, IComputeResource, IResourceWithEnvironment
public class AzureHostedAgentResource : Resource, IResourceWithEnvironment
Comment thread
eerhardt marked this conversation as resolved.
{
/// <summary>
/// Creates a new instance of the <see cref="AzureHostedAgentResource"/> class.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,9 @@ await interactionService.PromptMessageBoxAsync(
project = builder.ApplicationBuilder.CreateResourceBuilder(projResource);
}
}

builder.WithComputeEnvironment(project);

// Hosted Agent resource name
var agentName = $"{resource.Name}-ha";
if (builder.ApplicationBuilder.TryCreateResourceBuilder<AzureHostedAgentResource>(agentName, out var rb))
Expand Down Expand Up @@ -304,9 +307,12 @@ await interactionService.PromptMessageBoxAsync(
{
throw new InvalidOperationException($"Unable to create hosted agent for resource '{resource.Name}' because it is not a container, executable, or project resource.");
}

target = resource;
else
{
target = resource;
}
}

// Create a separate agent resource to host the deployment
var agent = new AzureHostedAgentResource(agentName, target, configure);

Expand Down
2 changes: 1 addition & 1 deletion src/Aspire.Hosting.Foundry/Project/ProjectResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public AzureCognitiveServicesProjectResource([ResourceName] string name, Action<
return Task.CompletedTask;
},
Resource = this,
DependsOnSteps = [AzureEnvironmentResource.PrepareResourcesStepName],
DependsOnSteps = [AzureEnvironmentResource.PrepareResourcesStepName, WellKnownPipelineSteps.ValidateComputeEnvironments],
RequiredBySteps = [WellKnownPipelineSteps.BeforeStart]
};
steps.Add(removeDefaultContainerRegistryStep);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ public KubernetesEnvironmentResource(string name) : base(name)
Name = $"prepare-deployment-targets-{Name}",
Description = $"Prepares Kubernetes deployment targets for {Name}.",
Action = ctx => PrepareDeploymentTargetsAsync(ctx),
DependsOnSteps = [WellKnownPipelineSteps.ValidateComputeEnvironments],
RequiredBySteps = [WellKnownPipelineSteps.BeforeStart]
};

Expand Down
13 changes: 11 additions & 2 deletions src/Aspire.Hosting/ApplicationModel/ResourceExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,7 @@ internal static bool IsBuildOnlyContainer(this IResource resource)
if (resource.TryGetLastAnnotation<ComputeEnvironmentAnnotation>(out var computeEnvironmentAnnotation))
{
// If you have a ComputeEnvironmentAnnotation, it means the resource is bound to a specific compute environment.
// Skip the annotation if it doesn't match the specified computeEnvironmentResource.
// Skip the annotation if it doesn't match the specified targetComputeEnvironment.
if (targetComputeEnvironment is not null && targetComputeEnvironment != computeEnvironmentAnnotation.ComputeEnvironment)
{
return null;
Expand All @@ -1024,7 +1024,16 @@ internal static bool IsBuildOnlyContainer(this IResource resource)
throw new InvalidOperationException($"Resource '{resource.Name}' has multiple compute environments - '{computeEnvironmentNames}'. Please specify a single compute environment using 'WithComputeEnvironment'.");
}

return annotations[0];
var deploymentTargetAnnotation = annotations[0];

// If you have a DeploymentTargetAnnotation, it means the resource is bound to a specific compute environment.
// Skip the annotation if it doesn't match the specified targetComputeEnvironment.
if (targetComputeEnvironment is not null && targetComputeEnvironment != deploymentTargetAnnotation.ComputeEnvironment)
{
return null;
}

return deploymentTargetAnnotation;
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ public DistributedApplicationPipeline()

_steps.Add(new PipelineStep
{
Name = "validate-compute-environments",
Name = WellKnownPipelineSteps.ValidateComputeEnvironments,
Description = "Validates compute resource bindings before startup.",
Action = static context =>
{
Expand Down
6 changes: 6 additions & 0 deletions src/Aspire.Hosting/Pipelines/WellKnownPipelineSteps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ public static class WellKnownPipelineSteps
[AspireValue("WellKnownPipelineSteps")]
public const string Diagnostics = "diagnostics";

/// <summary>
/// The step that validates compute resources are assigned to unambiguous compute environments.
Comment thread
eerhardt marked this conversation as resolved.
/// </summary>
[AspireValue("WellKnownPipelineSteps")]
public const string ValidateComputeEnvironments = "validate-compute-environments";

Comment thread
eerhardt marked this conversation as resolved.
/// <summary>
/// The step that runs before the application starts.
/// </summary>
Expand Down
30 changes: 30 additions & 0 deletions tests/Aspire.Hosting.Azure.Tests/AzureDeployerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1271,6 +1271,36 @@ public async Task DeployAsync_WithRedisAccessKeyAuthentication_CreatesCorrectDep
await Verify(logs);
}

[Fact]
public async Task DeployAsync_WithFoundryAndAzureContainerApps_CreatesCorrectDependencies()
{
using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, step: "diagnostics");
var mockActivityReporter = new TestPipelineActivityReporter(testOutputHelper);
ConfigureTestServices(builder, activityReporter: mockActivityReporter);

var foundryProject = builder.AddFoundry("foundry")
.AddProject("foundry-project");
var acaEnv = builder.AddAzureContainerAppEnvironment("aca-env");

builder.AddProject<Project>("agent", launchProfileName: null)
.PublishAsHostedAgent(foundryProject);

builder.AddProject<Project>("api", launchProfileName: null)
.WithExternalHttpEndpoints()
.WithComputeEnvironment(acaEnv);

using var app = builder.Build();
await app.StartAsync();
await app.WaitForShutdownAsync();

var logs = mockActivityReporter.LoggedMessages
.Where(s => s.StepTitle == "diagnostics")
.Select(s => s.Message)
.ToList();

await Verify(logs);
}

[Fact]
public async Task DeployAsync_WithPrivateEndpoints_CreatesCorrectDependencies()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[
[
PIPELINE DEPENDENCY GRAPH DIAGNOSTICS
=====================================

Expand All @@ -15,9 +15,9 @@ This shows the order in which steps would execute, respecting all dependencies.
Steps with no dependencies run first, followed by steps that depend on them.

1. azure-prepare-resources
2. prepare-azure-app-service-env
3. validate-azure-app-service
4. validate-compute-environments
2. validate-compute-environments
3. prepare-azure-app-service-env
4. validate-azure-app-service
5. before-start
6. process-parameters
7. build-prereq
Expand Down Expand Up @@ -127,7 +127,7 @@ Step: login-to-acr-env-acr

Step: prepare-azure-app-service-env
Description: Prepares Azure App Service deployment targets for env.
Dependencies: ✓ azure-prepare-resources
Dependencies: ✓ azure-prepare-resources, ✓ validate-compute-environments
Resource: env (AzureAppServiceEnvironmentResource)

Step: print-api-summary
Expand Down Expand Up @@ -378,10 +378,10 @@ If targeting 'login-to-acr-env-acr':
[5] login-to-acr-env-acr

If targeting 'prepare-azure-app-service-env':
Direct dependencies: azure-prepare-resources
Total steps: 2
Direct dependencies: azure-prepare-resources, validate-compute-environments
Total steps: 3
Execution order:
[0] azure-prepare-resources
[0] azure-prepare-resources | validate-compute-environments (parallel)
[1] prepare-azure-app-service-env

If targeting 'print-api-summary':
Expand Down Expand Up @@ -600,4 +600,4 @@ If targeting 'validate-compute-environments':
[0] validate-compute-environments


]
]
Loading
Loading