mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-03-17 23:03:46 +01:00
* Add WireMockHealthCheck For use with Aspire, to make WaitFor(wiremock) more useful. Calls /__admin/health and checks the result, as well as checks if mappings using AdminApiMappingBuilder has been submitted to the server. This created a catch-22 problem where the mappings were not submitted until the health check was healthy, but the health check was not healthy until the mappings were submitted. To avoid this, the WireMockServerLifecycleHook class has been slightly re-arranged, and is now using the AfterEndpointsAllocatedAsync callback rather than the AfterResourcesCreatedAsync callback. Within which a separate Task is created that waits until the server is ready and submits the mappings. * Move WireMockMappingState to its own file * Dispose the cancellation tokens in WireMockServerLifecycleHook
126 lines
4.5 KiB
C#
126 lines
4.5 KiB
C#
// Copyright © WireMock.Net
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
using RestEase;
|
|
using Stef.Validation;
|
|
using WireMock.Client;
|
|
using WireMock.Client.Extensions;
|
|
using WireMock.Net.Aspire;
|
|
using WireMock.Util;
|
|
|
|
// ReSharper disable once CheckNamespace
|
|
namespace Aspire.Hosting.ApplicationModel;
|
|
|
|
/// <summary>
|
|
/// A resource that represents a WireMock.Net Server.
|
|
/// </summary>
|
|
public class WireMockServerResource : ContainerResource, IResourceWithServiceDiscovery
|
|
{
|
|
private const int EnhancedFileSystemWatcherTimeoutMs = 2000;
|
|
|
|
internal WireMockServerArguments Arguments { get; }
|
|
internal Lazy<IWireMockAdminApi> AdminApi => new(CreateWireMockAdminApi);
|
|
internal WireMockMappingState ApiMappingState { get; set; } = WireMockMappingState.NoMappings;
|
|
|
|
private ILogger? _logger;
|
|
private EnhancedFileSystemWatcher? _enhancedFileSystemWatcher;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="WireMockServerResource"/> class.
|
|
/// </summary>
|
|
/// <param name="name">The name of the resource.</param>
|
|
/// <param name="arguments">The arguments to start the WireMock.Net Server.</param>
|
|
public WireMockServerResource(string name, WireMockServerArguments arguments) : base(name)
|
|
{
|
|
Arguments = Guard.NotNull(arguments);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets an endpoint reference.
|
|
/// </summary>
|
|
/// <returns>An <see cref="EndpointReference"/> object representing the endpoint reference.</returns>
|
|
public EndpointReference GetEndpoint()
|
|
{
|
|
return new EndpointReference(this, "http");
|
|
}
|
|
|
|
internal void SetLogger(ILogger logger)
|
|
{
|
|
_logger = logger;
|
|
}
|
|
|
|
internal async Task WaitForHealthAsync(CancellationToken cancellationToken)
|
|
{
|
|
_logger?.LogInformation("Checking Health status from WireMock.Net");
|
|
await AdminApi.Value.WaitForHealthAsync(cancellationToken: cancellationToken);
|
|
}
|
|
|
|
internal async Task CallApiMappingBuilderActionAsync(CancellationToken cancellationToken)
|
|
{
|
|
if (Arguments.ApiMappingBuilder == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_logger?.LogInformation("Calling ApiMappingBuilder to add mappings to WireMock.Net");
|
|
|
|
var mappingBuilder = AdminApi.Value.GetMappingBuilder();
|
|
await Arguments.ApiMappingBuilder.Invoke(mappingBuilder, cancellationToken);
|
|
|
|
ApiMappingState = WireMockMappingState.Submitted;
|
|
}
|
|
|
|
internal void StartWatchingStaticMappings(CancellationToken cancellationToken)
|
|
{
|
|
if (!Arguments.WatchStaticMappings || string.IsNullOrEmpty(Arguments.MappingsPath))
|
|
{
|
|
return;
|
|
}
|
|
|
|
cancellationToken.Register(() =>
|
|
{
|
|
if (_enhancedFileSystemWatcher != null)
|
|
{
|
|
_enhancedFileSystemWatcher.EnableRaisingEvents = false;
|
|
_enhancedFileSystemWatcher.Created -= FileCreatedChangedOrDeleted;
|
|
_enhancedFileSystemWatcher.Changed -= FileCreatedChangedOrDeleted;
|
|
_enhancedFileSystemWatcher.Deleted -= FileCreatedChangedOrDeleted;
|
|
|
|
_enhancedFileSystemWatcher.Dispose();
|
|
_enhancedFileSystemWatcher = null;
|
|
}
|
|
});
|
|
|
|
_logger?.LogInformation("Starting to watch static mappings on path: '{Path}'. ", Arguments.MappingsPath);
|
|
|
|
_enhancedFileSystemWatcher = new EnhancedFileSystemWatcher(Arguments.MappingsPath, "*.json", EnhancedFileSystemWatcherTimeoutMs)
|
|
{
|
|
IncludeSubdirectories = true
|
|
};
|
|
_enhancedFileSystemWatcher.Created += FileCreatedChangedOrDeleted;
|
|
_enhancedFileSystemWatcher.Changed += FileCreatedChangedOrDeleted;
|
|
_enhancedFileSystemWatcher.Deleted += FileCreatedChangedOrDeleted;
|
|
_enhancedFileSystemWatcher.EnableRaisingEvents = true;
|
|
}
|
|
|
|
private IWireMockAdminApi CreateWireMockAdminApi()
|
|
{
|
|
var adminApi = RestClient.For<IWireMockAdminApi>(GetEndpoint().Url);
|
|
return Arguments.HasBasicAuthentication ?
|
|
adminApi.WithAuthorization(Arguments.AdminUsername!, Arguments.AdminPassword!) :
|
|
adminApi;
|
|
}
|
|
|
|
private async void FileCreatedChangedOrDeleted(object sender, FileSystemEventArgs args)
|
|
{
|
|
_logger?.LogInformation("MappingFile created, changed or deleted: '{0}'. Triggering ReloadStaticMappings.", args.FullPath);
|
|
try
|
|
{
|
|
await AdminApi.Value.ReloadStaticMappingsAsync();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger?.LogWarning(ex, "Error calling /__admin/mappings/reloadStaticMappings");
|
|
}
|
|
}
|
|
} |