From dca3fd02607ddf50f2381dafe33be295b6da73f8 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Fri, 27 Sep 2024 19:10:51 +0200 Subject: [PATCH] WireMock.Net.Testcontainers: Use 'sheyenrath/wiremock.net-alpine' image as default for Linux (#1181) * WireMock.Net.Testcontainers: Use 'sheyenrath/wiremock.net-alpine' image as default for Linux * ... * . * WithBindMount * fix * r * . --- .../Program.cs | 136 ++++++++++++++++-- .../WireMock.Net.TestcontainersExample.csproj | 32 ++--- .../WireMockContainerBuilder.cs | 96 +++++++++---- .../Testcontainers/TestcontainersTests.cs | 58 +++++++- 4 files changed, 265 insertions(+), 57 deletions(-) diff --git a/examples/WireMock.Net.TestcontainersExample/Program.cs b/examples/WireMock.Net.TestcontainersExample/Program.cs index 52a39c22..f9bf2498 100644 --- a/examples/WireMock.Net.TestcontainersExample/Program.cs +++ b/examples/WireMock.Net.TestcontainersExample/Program.cs @@ -1,7 +1,7 @@ // Copyright © WireMock.Net +using System.Runtime.InteropServices; using Newtonsoft.Json; -using Testcontainers.MsSql; using WireMock.Net.Testcontainers; namespace WireMock.Net.TestcontainersExample; @@ -10,17 +10,134 @@ internal class Program { private static async Task Main(string[] args) { - var container = new WireMockContainerBuilder() + var original = Console.ForegroundColor; + + try + { + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine("Linux"); + await TestAsync("sheyenrath/wiremock.net:1.6.4"); + await Task.Delay(1_000); + } + catch (Exception e) + { + Console.WriteLine(e); + } + finally + { + Console.ForegroundColor = original; + } + + try + { + Console.ForegroundColor = ConsoleColor.White; + Console.WriteLine("Linux Alpine"); + await TestAsync("sheyenrath/wiremock.net-alpine:1.6.4"); + await Task.Delay(1_000); + } + catch (Exception e) + { + Console.WriteLine(e); + } + finally + { + Console.ForegroundColor = original; + } + + try + { + Console.ForegroundColor = ConsoleColor.Gray; + Console.WriteLine("WithLinux"); + await TestAsync("WithLinux"); + await Task.Delay(1_000); + } + catch (Exception e) + { + Console.WriteLine(e); + } + finally + { + Console.ForegroundColor = original; + } + + try + { + Console.ForegroundColor = ConsoleColor.Cyan; + Console.WriteLine("Windows"); + await TestAsync("sheyenrath/wiremock.net-windows:1.6.4"); + await Task.Delay(1_000); + } + catch (Exception e) + { + Console.WriteLine(e); + } + finally + { + Console.ForegroundColor = original; + } + + try + { + Console.ForegroundColor = ConsoleColor.Blue; + Console.WriteLine("WithWindows"); + await TestAsync("WithWindows"); + await Task.Delay(1_000); + } + catch (Exception e) + { + Console.WriteLine(e); + } + finally + { + Console.ForegroundColor = original; + } + + try + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine("Automatic"); + await TestAsync(); + } + finally + { + Console.ForegroundColor = original; + } + } + + private static async Task TestAsync(string? image = null) + { + var builder = new WireMockContainerBuilder() .WithAdminUserNameAndPassword("x", "y") - .WithMappings(@"C:\Dev\GitHub\WireMock.Net\examples\WireMock.Net.Console.NET6\__admin\mappings") .WithWatchStaticMappings(true) .WithAutoRemove(true) - .WithCleanUp(true) - .Build(); + .WithCleanUp(true); - await container.StartAsync().ConfigureAwait(false); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + builder = builder.WithMappings(@"C:\Dev\GitHub\WireMock.Net\examples\WireMock.Net.Console.NET6\__admin\mappings"); + } + else + { + builder = builder.WithMappings("./examples/WireMock.Net.Console.NET6/__admin/mappings"); + } - var logs = await container.GetLogsAsync(DateTime.Now.AddDays(-1)).ConfigureAwait(false); + if (image != null) + { + builder = image switch + { + "WithWindows" => builder.WithWindowsImage(), + "WithLinux" => builder.WithLinuxImage(), + _ => builder.WithImage(image) + }; + } + + var container = builder.Build(); + + await container.StartAsync(); + + await Task.Delay(1_000); + + var logs = await container.GetLogsAsync(DateTime.Now.AddDays(-1)); Console.WriteLine("logs = " + logs.Stdout); var restEaseApiClient = container.CreateWireMockAdminClient(); @@ -36,10 +153,5 @@ internal class Program Console.WriteLine("result = " + result); await container.StopAsync(); - - var sql = new MsSqlBuilder() - .WithAutoRemove(true) - .WithCleanUp(true) - .Build(); } } \ No newline at end of file diff --git a/examples/WireMock.Net.TestcontainersExample/WireMock.Net.TestcontainersExample.csproj b/examples/WireMock.Net.TestcontainersExample/WireMock.Net.TestcontainersExample.csproj index 9090e001..d6cb0d69 100644 --- a/examples/WireMock.Net.TestcontainersExample/WireMock.Net.TestcontainersExample.csproj +++ b/examples/WireMock.Net.TestcontainersExample/WireMock.Net.TestcontainersExample.csproj @@ -1,24 +1,20 @@ - - Exe - net8.0 - enable - enable - + + Exe + net8.0 + enable + enable + - - - + + + - - - - - - - PreserveNewest - - + + + PreserveNewest + + diff --git a/src/WireMock.Net.Testcontainers/WireMockContainerBuilder.cs b/src/WireMock.Net.Testcontainers/WireMockContainerBuilder.cs index e74ffdab..885cf7bb 100644 --- a/src/WireMock.Net.Testcontainers/WireMockContainerBuilder.cs +++ b/src/WireMock.Net.Testcontainers/WireMockContainerBuilder.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; using System.Threading.Tasks; using Docker.DotNet.Models; using DotNet.Testcontainers.Builders; @@ -17,15 +18,14 @@ namespace WireMock.Net.Testcontainers; /// public sealed class WireMockContainerBuilder : ContainerBuilder { - private readonly Dictionary _info = new() + private const string DefaultLogger = "WireMockConsoleLogger"; + private readonly Dictionary _info = new() { - { false, new ContainerInfo("sheyenrath/wiremock.net:latest", "/app/__admin/mappings") }, - { true, new ContainerInfo("sheyenrath/wiremock.net-windows:latest", @"c:\app\__admin\mappings") } + { OSPlatform.Linux, new ContainerInfo("sheyenrath/wiremock.net-alpine", "/app/__admin/mappings") }, + { OSPlatform.Windows, new ContainerInfo("sheyenrath/wiremock.net-windows", @"c:\app\__admin\mappings") } }; - private const string DefaultLogger = "WireMockConsoleLogger"; - - private readonly Lazy> _isWindowsAsLazy = new(async () => + private readonly Lazy> _getOSAsLazy = new(async () => { if (TestcontainersSettings.OS.DockerEndpointAuthConfig == null) { @@ -36,9 +36,12 @@ public sealed class WireMockContainerBuilder : ContainerBuilder -1; + return version.Os.IndexOf("Windows", StringComparison.OrdinalIgnoreCase) >= 0 ? OSPlatform.Windows : OSPlatform.Linux; }); + private OSPlatform? _imageOS; + private string? _staticMappingsPath; + /// /// Initializes a new instance of the class. /// @@ -48,14 +51,36 @@ public sealed class WireMockContainerBuilder : ContainerBuilder - /// Automatically set the correct image (Linux or Windows) for WireMock which to create the container. + /// Automatically use the correct image for WireMock. + /// For Linux this is "sheyenrath/wiremock.net-alpine:latest" + /// For Windows this is "sheyenrath/wiremock.net-windows:latest" /// /// A configured instance of [PublicAPI] public WireMockContainerBuilder WithImage() { - var isWindows = _isWindowsAsLazy.Value.GetAwaiter().GetResult(); - return WithImage(_info[isWindows].Image); + _imageOS ??= _getOSAsLazy.Value.GetAwaiter().GetResult(); + return WithImage(_imageOS.Value); + } + + /// + /// Automatically use a Linux image for WireMock. This is "sheyenrath/wiremock.net-alpine:latest" + /// + /// A configured instance of + [PublicAPI] + public WireMockContainerBuilder WithLinuxImage() + { + return WithImage(OSPlatform.Linux); + } + + /// + /// Automatically use a Windows image for WireMock. This is "sheyenrath/wiremock.net-windows:latest" + /// + /// A configured instance of + [PublicAPI] + public WireMockContainerBuilder WithWindowsImage() + { + return WithImage(OSPlatform.Windows); } /// @@ -118,13 +143,9 @@ public sealed class WireMockContainerBuilder : ContainerBuilder public override WireMockContainer Build() { - Validate(); + var builder = this; - return new WireMockContainer(DockerResourceConfiguration); + // In case no image has been set, set the image using internal logic. + if (DockerResourceConfiguration.Image == null) + { + builder = WithImage(); + } + + // In case the _imageOS is not set, determine it from the Image FullName. + if (_imageOS == null) + { + if (builder.DockerResourceConfiguration.Image.FullName.IndexOf("wiremock.net", StringComparison.OrdinalIgnoreCase) < 0) + { + throw new InvalidOperationException(); + } + + _imageOS = builder.DockerResourceConfiguration.Image.FullName.IndexOf("windows", StringComparison.OrdinalIgnoreCase) >= 0 ? OSPlatform.Windows : OSPlatform.Linux; + } + + if (!string.IsNullOrEmpty(_staticMappingsPath)) + { + builder = builder.WithBindMount(_staticMappingsPath, _info[_imageOS.Value].MappingsPath); + } + + builder.Validate(); + + return new WireMockContainer(builder.DockerResourceConfiguration); } /// @@ -148,14 +193,7 @@ public sealed class WireMockContainerBuilder : ContainerBuilder