Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,5 @@
/// </summary>
/// <param name="name">The name of the resource.</param>
/// <param name="workingDirectory">The working directory to use for the command.</param>
public class RustAppExecutableResource(string name, string workingDirectory)
: ExecutableResource(name, "cargo", workingDirectory), IResourceWithServiceDiscovery
{

}
public class RustAppExecutableResource(string name, string workingDirectory, string command = "cargo")
: ExecutableResource(name, command, workingDirectory), IResourceWithServiceDiscovery;
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,72 @@ namespace Aspire.Hosting;
public static class RustAppHostingExtension
{
/// <summary>
/// Adds a Rust application to the application model. Executes the executable Rust app.
/// Adds a Rust application to the application model, using the cargo cli.
/// </summary>
/// <param name="builder">The <see cref="IDistributedApplicationBuilder"/> to add the resource to.</param>
/// <param name="name">The name of the resource.</param>
/// <param name="workingDirectory">The working directory to use for the command.</param>
/// <param name="args">The optional arguments to be passed to the executable when it is started.</param>
/// <returns>A reference to the <see cref="IResourceBuilder{T}"/>.</returns>
[AspireExport("addRustApp", Description = "Adds a Rust application to the application model")]
public static IResourceBuilder<RustAppExecutableResource> AddRustApp(this IDistributedApplicationBuilder builder, [ResourceName] string name, string workingDirectory, string[]? args = null)
public static IResourceBuilder<RustAppExecutableResource> AddRustApp(
this IDistributedApplicationBuilder builder,
[ResourceName] string name,
string workingDirectory,
string[]? args = null
)
{
ArgumentNullException.ThrowIfNull(builder, nameof(builder));
ArgumentException.ThrowIfNullOrWhiteSpace(name, nameof(name));
ArgumentException.ThrowIfNullOrWhiteSpace(workingDirectory, nameof(workingDirectory));
ArgumentNullException.ThrowIfNull(builder);
ArgumentException.ThrowIfNullOrWhiteSpace(name);
ArgumentException.ThrowIfNullOrWhiteSpace(workingDirectory);

string[] allArgs = args is { Length: > 0 }
? ["run", .. args]
: ["run"];

return builder.AddRustApp(name, workingDirectory, command: "cargo", allArgs);
}

/// <summary>
/// Adds a Rust application to the application model, using the bacon cli.
/// </summary>
/// <param name="builder">The <see cref="IDistributedApplicationBuilder"/> to add the resource to.</param>
/// <param name="name">The name of the resource.</param>
/// <param name="workingDirectory">The working directory to use for the command.</param>
/// <param name="args">The optional arguments to be passed to the executable when it is started.</param>
/// <returns>A reference to the <see cref="IResourceBuilder{T}"/>.</returns>
[AspireExport("addBaconApp", Description = "Adds a Rust application to the application model")]
public static IResourceBuilder<RustAppExecutableResource> AddBaconApp(
this IDistributedApplicationBuilder builder,
[ResourceName] string name,
string workingDirectory,
string[]? args = null
)
{
ArgumentNullException.ThrowIfNull(builder);
ArgumentException.ThrowIfNullOrWhiteSpace(name);
ArgumentException.ThrowIfNullOrWhiteSpace(workingDirectory);

string[] allArgs = args is { Length: > 0 }
? args
: ["run"];

return builder.AddRustApp(name, workingDirectory, command: "bacon", allArgs);
}

private static IResourceBuilder<RustAppExecutableResource> AddRustApp(
this IDistributedApplicationBuilder builder,
string name,
string workingDirectory,
string command,
string[] args)
{
workingDirectory = Path.Combine(builder.AppHostDirectory, workingDirectory).NormalizePathForCurrentPlatform();
var resource = new RustAppExecutableResource(name, workingDirectory);
var resource = new RustAppExecutableResource(name, workingDirectory, command);

return builder.AddResource(resource)
.WithRustDefaults()
.WithArgs(allArgs)
.WithArgs(args)
.PublishAsDockerFile();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// 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;
using CommunityToolkit.Aspire.Utils;
using CommunityToolkit.Aspire.Testing;

namespace CommunityToolkit.Aspire.Hosting.Rust.Tests;
public class AddBaconAppTests
{
[Fact]
public async Task AddBaconAppAddsAnnotationMetadata()
{
var appBuilder = DistributedApplication.CreateBuilder();

var workingDirectory = "../../examples/rust/actix_api";
var baconApp = appBuilder.AddBaconApp("bacon-app", workingDirectory);

await using var app = appBuilder.Build();

var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();

var resource = Assert.Single(appModel.Resources.OfType<RustAppExecutableResource>());
workingDirectory = Path.Combine(appBuilder.AppHostDirectory, workingDirectory).NormalizePathForCurrentPlatform();
Assert.Equal("bacon-app", resource.Name);
Assert.Equal(workingDirectory, resource.WorkingDirectory);
Assert.Equal("bacon", resource.Command);
var args = await resource.GetArgumentListAsync();
Assert.Collection(args,
arg => Assert.Equal("run", arg));
}

[Fact]
public async Task AddBaconAppWithArgsAddsAnnotationMetadata()
{
var appBuilder = DistributedApplication.CreateBuilder();

var workingDirectory = "../../examples/rust/actix_api";
var baconApp = appBuilder.AddBaconApp("bacon-app", workingDirectory, ["check"]);

await using var app = appBuilder.Build();

var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();

var resource = Assert.Single(appModel.Resources.OfType<RustAppExecutableResource>());
workingDirectory = Path.Combine(appBuilder.AppHostDirectory, workingDirectory).NormalizePathForCurrentPlatform();
Assert.Equal("bacon-app", resource.Name);
Assert.Equal(workingDirectory, resource.WorkingDirectory);
Assert.Equal("bacon", resource.Command);
var args = await resource.GetArgumentListAsync();
Assert.Collection(args,
arg => Assert.Equal("check", arg));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// 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;

namespace CommunityToolkit.Aspire.Hosting.Rust.Tests;

public class BaconAppPublicApiTests
{
[Fact]
public void AddBaconAppShouldThrowWhenBuilderIsNull()
{
IDistributedApplicationBuilder builder = null!;
const string name = "bacon-app";
const string workingDirectory = "bacon_app";
var action = () => builder.AddBaconApp(name, workingDirectory);

var exception = Assert.Throws<ArgumentNullException>(action);
Assert.Equal(nameof(builder), exception.ParamName);
}

[Fact]
public void AddBaconAppShouldThrowWhenNameIsNull()
{
IDistributedApplicationBuilder builder = new DistributedApplicationBuilder([]);
const string name = null!;
const string workingDirectory = "bacon_app";

var action = () => builder.AddBaconApp(name!, workingDirectory);

var exception = Assert.Throws<ArgumentNullException>(action);
Assert.Equal(nameof(name), exception.ParamName);
}

[Fact]
public void AddBaconAppShouldThrowWhenWorkingDirectoryIsNull()
{
IDistributedApplicationBuilder builder = new DistributedApplicationBuilder([]);
const string name = "bacon-app";
const string workingDirectory = null!;

var action = () => builder.AddBaconApp(name, workingDirectory!);

var exception = Assert.Throws<ArgumentNullException>(action);
Assert.Equal(nameof(workingDirectory), exception.ParamName);
}
}
Loading