Skip to content

Commit 473e77e

Browse files
authored
Follow-ups to Docker Compose as compute environment resource (#8834)
* Follow-ups to Docker Compose as compute environment resource * Throw if DockerComposeEnvironmentResource not found
1 parent 1db6fb2 commit 473e77e

File tree

7 files changed

+59
-13
lines changed

7 files changed

+59
-13
lines changed

playground/publishers/Publishers.AppHost/Program.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
builder.AddAzureContainerAppEnvironment("env");
99

10-
builder.AddDockerComposePublisher();
10+
builder.AddDockerComposeEnvironment("docker-env");
1111

1212
builder.AddKubernetesPublisher();
1313

src/Aspire.Hosting.Docker/DockerComposeEnvironmentExtensions.cs

+8
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ public static IResourceBuilder<DockerComposeEnvironmentResource> AddDockerCompos
2828
var resource = new DockerComposeEnvironmentResource(name);
2929
builder.Services.TryAddLifecycleHook<DockerComposeInfrastructure>();
3030
builder.AddDockerComposePublisher(name);
31+
if (builder.ExecutionContext.IsRunMode)
32+
{
33+
34+
// Return a builder that isn't added to the top-level application builder
35+
// so it doesn't surface as a resource.
36+
return builder.CreateResourceBuilder(resource);
37+
38+
}
3139
return builder.AddResource(resource);
3240
}
3341
}

src/Aspire.Hosting.Docker/DockerComposeEnvironmentResource.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
#pragma warning disable ASPIRECOMPUTE001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
5+
46
using Aspire.Hosting.ApplicationModel;
57

68
namespace Aspire.Hosting.Docker;
@@ -12,7 +14,7 @@ namespace Aspire.Hosting.Docker;
1214
/// Initializes a new instance of the <see cref="DockerComposeEnvironmentResource"/> class.
1315
/// </remarks>
1416
/// <param name="name">The name of the Docker Compose environment.</param>
15-
public class DockerComposeEnvironmentResource(string name) : Resource(name)
17+
public class DockerComposeEnvironmentResource(string name) : Resource(name), IComputeEnvironmentResource
1618
{
1719
/// <summary>
1820
/// Gets the collection of environment variables captured from the Docker Compose environment.

src/Aspire.Hosting.Docker/DockerComposePublishingContext.cs

+9-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ private async Task WriteDockerComposeOutputAsync(DistributedApplicationModel mod
6868
if (environment == null)
6969
{
7070
// No Docker Compose environment found
71-
return;
71+
throw new InvalidOperationException($"No Docker Compose environment found. Ensure a Docker Compose environment is registered by calling {nameof(DockerComposeEnvironmentExtensions.AddDockerComposeEnvironment)}.");
7272
}
7373

7474
var defaultNetwork = new Network
@@ -99,6 +99,14 @@ private async Task WriteDockerComposeOutputAsync(DistributedApplicationModel mod
9999
defaultNetwork.Name,
100100
];
101101

102+
if (serviceResource.TargetResource.TryGetAnnotationsOfType<DockerComposeServiceCustomizationAnnotation>(out var annotations))
103+
{
104+
foreach (var a in annotations)
105+
{
106+
a.Configure(serviceResource, composeService);
107+
}
108+
}
109+
102110
composeFile.AddService(composeService);
103111
}
104112
}

src/Aspire.Hosting.Docker/DockerComposeServiceExtensions.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
#pragma warning disable ASPIRECOMPUTE001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
5+
46
using Aspire.Hosting.ApplicationModel;
57
using Aspire.Hosting.Docker;
68
using Aspire.Hosting.Docker.Resources.ComposeNodes;
@@ -32,7 +34,7 @@ public static class DockerComposeServiceExtensions
3234
/// </code>
3335
/// </example>
3436
public static IResourceBuilder<T> PublishAsDockerComposeService<T>(this IResourceBuilder<T> builder, Action<DockerComposeServiceResource, Service> configure)
35-
where T : IResource
37+
where T : IComputeResource
3638
{
3739
ArgumentNullException.ThrowIfNull(builder);
3840
ArgumentNullException.ThrowIfNull(configure);

src/Aspire.Hosting.Docker/DockerComposeServiceResource.cs

-9
Original file line numberDiff line numberDiff line change
@@ -81,15 +81,6 @@ private Service GetComposeService()
8181
AddPorts(composeService);
8282
AddVolumes(composeService);
8383
SetDependsOn(composeService);
84-
85-
if (resource.TryGetAnnotationsOfType<DockerComposeServiceCustomizationAnnotation>(out var annotations))
86-
{
87-
foreach (var a in annotations)
88-
{
89-
a.Configure(this, composeService);
90-
}
91-
}
92-
9384
return composeService;
9485
}
9586

tests/Aspire.Hosting.Docker.Tests/DockerComposePublisherTests.cs

+35
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,37 @@ public async Task PublishAsync_GeneratesValidDockerComposeFile()
156156
envContent, ignoreAllWhiteSpace: true, ignoreLineEndingDifferences: true);
157157
}
158158

159+
[Fact]
160+
public async Task PublishAsync_ThrowsWhenDockerComposeEnvironmentNotAdded()
161+
{
162+
using var tempDir = new TempDirectory();
163+
// Arrange
164+
var options = new OptionsMonitor(new DockerComposePublisherOptions { OutputPath = tempDir.Path });
165+
var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish);
166+
167+
// Add a simple container resource
168+
builder.AddContainer("cache", "redis");
169+
170+
var app = builder.Build();
171+
var model = app.Services.GetRequiredService<DistributedApplicationModel>();
172+
173+
await ExecuteBeforeStartHooksAsync(app, default);
174+
175+
var publisher = new DockerComposePublisher("test",
176+
options,
177+
NullLogger<DockerComposePublisher>.Instance,
178+
builder.ExecutionContext,
179+
new MockImageBuilder()
180+
);
181+
182+
// Act & Assert
183+
var exception = await Assert.ThrowsAsync<InvalidOperationException>(
184+
() => publisher.PublishAsync(model, default)
185+
);
186+
187+
Assert.Contains("No Docker Compose environment found. Ensure a Docker Compose environment is registered by calling AddDockerComposeEnvironment.", exception.Message, StringComparison.OrdinalIgnoreCase);
188+
}
189+
159190
[Fact]
160191
public async Task DockerComposeCorrectlyEmitsPortMappings()
161192
{
@@ -267,6 +298,9 @@ public async Task DockerComposeAppliesServiceCustomizations()
267298

268299
// Set a restart policy
269300
composeService.Restart = "always";
301+
302+
// Add a custom network
303+
composeService.Networks.Add("custom-network");
270304
});
271305

272306
var app = builder.Build();
@@ -301,6 +335,7 @@ public async Task DockerComposeAppliesServiceCustomizations()
301335
CUSTOM_ENV: "custom-value"
302336
networks:
303337
- "aspire"
338+
- "custom-network"
304339
restart: "always"
305340
labels:
306341
custom-label: "test-value"

0 commit comments

Comments
 (0)