Skip to content

Commit

Permalink
Review feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
ReubenBond committed Feb 29, 2024
1 parent acdda59 commit f26e398
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 76 deletions.
97 changes: 33 additions & 64 deletions src/Aspire.Hosting.Testing/DistributedApplicationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,47 +19,10 @@ public static class DistributedApplicationExtensions
/// <returns>The <see cref="HttpClient"/>.</returns>
public static HttpClient CreateHttpClient(this DistributedApplication app, string resourceName, string? endpointName = default)
{
var applicationModel = app.Services.GetRequiredService<DistributedApplicationModel>();

var resources = applicationModel.Resources;
var resource = resources.FirstOrDefault(r => string.Equals(r.Name, resourceName, StringComparison.OrdinalIgnoreCase));

if (resource is null)
{
throw new ArgumentException($"Resource '{resourceName}' not found", nameof(resourceName));
}

if (!resource.TryGetAllocatedEndPoints(out var endpoints))
{
throw new InvalidOperationException($"Cannot create a client for resource '{resourceName}' because it has no allocated endpoints.");
}

AllocatedEndpointAnnotation? endpoint = null;

if (!string.IsNullOrEmpty(endpointName))
{
endpoint = endpoints.FirstOrDefault(e => string.Equals(e.Name, endpointName, StringComparison.OrdinalIgnoreCase));

if (endpoint is null)
{
throw new ArgumentException($"Endpoint '{endpointName}' for resource '{resourceName}' not found", nameof(endpointName));
}
}
else
{
endpoint = endpoints.FirstOrDefault(e =>
string.Equals(e.UriScheme, "http", StringComparison.OrdinalIgnoreCase) || string.Equals(e.UriScheme, "https", StringComparison.OrdinalIgnoreCase));

if (endpoint is null)
{
throw new InvalidOperationException($"Cannot create a client for resource '{resourceName}' because it has no allocated HTTP endpoints.");
}
}

var baseUri = GetEndpointUriStringCore(app, resourceName, endpointName);
var clientFactory = app.Services.GetRequiredService<IHttpClientFactory>();

var client = clientFactory.CreateClient();
client.BaseAddress = new(endpoint.UriString);
client.BaseAddress = new(baseUri);

return client;
}
Expand All @@ -73,14 +36,7 @@ public static HttpClient CreateHttpClient(this DistributedApplication app, strin
/// <exception cref="ArgumentException">The resource was not found or does not expose a connection string.</exception>
public static string? GetConnectionString(this DistributedApplication app, string resourceName)
{
var applicationModel = app.Services.GetRequiredService<DistributedApplicationModel>();
var resource = applicationModel.Resources.FirstOrDefault(r => string.Equals(r.Name, resourceName, StringComparison.OrdinalIgnoreCase));

if (resource is null)
{
throw new ArgumentException($"Resource '{resourceName}' not found.", nameof(resourceName));
}

var resource = GetResource(app, resourceName);
if (resource is not IResourceWithConnectionString resourceWithConnectionString)
{
throw new ArgumentException($"Resource '{resourceName}' does not expose a connection string.", nameof(resourceName));
Expand All @@ -98,44 +54,57 @@ public static HttpClient CreateHttpClient(this DistributedApplication app, strin
/// <returns>A URI representation of the endpoint.</returns>
/// <exception cref="ArgumentException">The resource was not found, no matching endpoint was found, or multiple endpoints were found.</exception>
/// <exception cref="InvalidOperationException">The resource has no endpoints.</exception>
public static Uri GetEndpoint(this DistributedApplication app, string resourceName, string? endpointName = default)
public static Uri GetEndpoint(this DistributedApplication app, string resourceName, string? endpointName = default) => new(GetEndpointUriStringCore(app, resourceName, endpointName));

private static IResource GetResource(DistributedApplication app, string resourceName)
{
var applicationModel = app.Services.GetRequiredService<DistributedApplicationModel>();

var resources = applicationModel.Resources;
var resource = resources.FirstOrDefault(r => string.Equals(r.Name, resourceName, StringComparison.OrdinalIgnoreCase));
var resource = resources.SingleOrDefault(r => string.Equals(r.Name, resourceName, StringComparison.OrdinalIgnoreCase));

if (resource is null)
{
throw new ArgumentException($"Resource '{resourceName}' not found", nameof(resourceName));
throw new ArgumentException($"Resource '{resourceName}' not found.", nameof(resourceName));
}

return resource;
}

private static string GetEndpointUriStringCore(DistributedApplication app, string resourceName, string? endpointName = default)
{
var resource = GetResource(app, resourceName);
if (!resource.TryGetAllocatedEndPoints(out var endpoints))
{
throw new InvalidOperationException($"Resource '{resourceName}' has no allocated endpoints.");
}

AllocatedEndpointAnnotation? endpoint = null;
var endpointList = endpoints.ToList();
AllocatedEndpointAnnotation? endpoint;
if (!string.IsNullOrEmpty(endpointName))
{
endpoint = endpointList.FirstOrDefault(e => string.Equals(e.Name, endpointName, StringComparison.OrdinalIgnoreCase));

if (endpoint is null)
{
throw new ArgumentException($"Resource '{resourceName}' does not have an endpoint named '{endpointName}'.", nameof(endpointName));
}
endpoint = GetEndpointOrDefault(endpoints, resourceName, endpointName);
}
else
{
if (endpointList.Count > 1)
{
throw new ArgumentException($"Resource '{resourceName}' has multiple endpoints but no endpoint name was specified.", nameof(endpointName));
}
endpoint = GetEndpointOrDefault(endpoints, resourceName, "http") ?? GetEndpointOrDefault(endpoints, resourceName, "https");
}

endpoint = endpointList[0];
if (endpoint is null)
{
throw new ArgumentException($"Endpoint '{endpointName}' for resource '{resourceName}' not found.", nameof(endpointName));
}

return new(endpoint.UriString);
return endpoint.UriString;
}

static AllocatedEndpointAnnotation? GetEndpointOrDefault(IEnumerable<AllocatedEndpointAnnotation> endpoints, string resourceName, string? endpointName)
{
var filteredEndpoints = endpoints.Where(e => string.Equals(e.Name, endpointName, StringComparison.OrdinalIgnoreCase)).ToList();
return filteredEndpoints.Count switch
{
0 => null,
1 => filteredEndpoints[0],
_ => throw new InvalidOperationException($"Resource '{resourceName}' has multiple endpoints named '{endpointName}'."),
};
}
}
14 changes: 2 additions & 12 deletions tests/Aspire.Hosting.Testing.Tests/TestingBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public async Task HasEndPoints()
}

[LocalOnlyFact]
public async Task CanRemoveResources()
public async Task CanGetResources()
{
var appHost = new DistributedApplicationTestingBuilder<Program>();
appHost.Resources.Remove(appHost.Resources.Single(r => r.Name == "redis1"));
Expand All @@ -39,17 +39,7 @@ public async Task CanRemoveResources()

// Ensure that the resource which we added is present in the model.
var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();
Assert.DoesNotContain(appModel.GetContainerResources(), c => c.Name == "redis1");
Assert.Contains(appModel.GetContainerResources(), c => c.Name == "redis1");
Assert.Contains(appModel.GetProjectResources(), p => p.Name == "myworker1");

// Get an endpoint from a resource
var workerEndpoint = app.GetEndpoint("myworker1", "myendpoint1");
Assert.NotNull(workerEndpoint);
Assert.True(workerEndpoint.Host.Length > 0);

// Get a connection string from a resource
var pgConnectionString = app.GetConnectionString("postgres1");
Assert.NotNull(pgConnectionString);
Assert.True(pgConnectionString.Length > 0);
}
}

0 comments on commit f26e398

Please sign in to comment.