| | | 1 | | using DotNet.Testcontainers.Builders; |
| | | 2 | | using DotNet.Testcontainers.Containers; |
| | | 3 | | using pva.Helpers; |
| | | 4 | | using System.Net.NetworkInformation; |
| | | 5 | | |
| | | 6 | | namespace pva.SuperV.TestContainers |
| | | 7 | | { |
| | | 8 | | public class TDengineContainer : IAsyncDisposable |
| | | 9 | | { |
| | | 10 | | private IContainer? tdEngineContainer; |
| | | 11 | | private bool disposedValue; |
| | | 12 | | |
| | | 13 | | private static void WaitForPort(int port) |
| | 12 | 14 | | { |
| | | 15 | | const int MaxWaitIndex = 50; |
| | 12 | 16 | | IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties(); |
| | 12 | 17 | | int index = 0; |
| | 1779 | 18 | | while (index < MaxWaitIndex && ipGlobalProperties.GetActiveTcpConnections().Any(pr => pr.LocalEndPoint.Port |
| | 0 | 19 | | { |
| | 0 | 20 | | Thread.Sleep(100); |
| | 0 | 21 | | index++; |
| | 0 | 22 | | } |
| | 12 | 23 | | if (index == MaxWaitIndex) |
| | 0 | 24 | | { |
| | 0 | 25 | | throw new ApplicationException($"Port 6030 is in use after {MaxWaitIndex * 100} msecs"); |
| | | 26 | | } |
| | 12 | 27 | | } |
| | | 28 | | |
| | | 29 | | public async Task<string> StartTDengineContainerAsync() |
| | 12 | 30 | | { |
| | 12 | 31 | | if (tdEngineContainer is null) |
| | 12 | 32 | | { |
| | 12 | 33 | | Console.WriteLine("Starting TD engine container"); |
| | 12 | 34 | | WaitForPort(6030); |
| | 12 | 35 | | tdEngineContainer = new ContainerBuilder("tdengine/tsdb:3.4.0.2") |
| | 12 | 36 | | .WithPortBinding(6030) |
| | 12 | 37 | | .WithPortBinding(6031) |
| | 12 | 38 | | .WithPortBinding(6032) |
| | 12 | 39 | | .WithPortBinding(6033) |
| | 12 | 40 | | .WithPortBinding(6034) |
| | 12 | 41 | | .WithPortBinding(6035) |
| | 12 | 42 | | .WithPortBinding(6036) |
| | 12 | 43 | | .WithPortBinding(6037) |
| | 12 | 44 | | .WithPortBinding(6038) |
| | 12 | 45 | | .WithPortBinding(6039) |
| | 12 | 46 | | .WithPortBinding(6040) |
| | 12 | 47 | | .WithPortBinding(6041) |
| | 12 | 48 | | .WithPortBinding(6042) |
| | 12 | 49 | | .WithPortBinding(6043) |
| | 12 | 50 | | .WithPortBinding(6044) |
| | 12 | 51 | | .WithPortBinding(6045) |
| | 12 | 52 | | .WithPortBinding(6046) |
| | 12 | 53 | | .WithPortBinding(6047) |
| | 12 | 54 | | .WithPortBinding(6048) |
| | 12 | 55 | | .WithPortBinding(6049) |
| | 12 | 56 | | .WithPortBinding(6050) |
| | 12 | 57 | | .WithPortBinding(6051) |
| | 12 | 58 | | .WithPortBinding(6052) |
| | 12 | 59 | | .WithPortBinding(6053) |
| | 12 | 60 | | .WithPortBinding(6054) |
| | 12 | 61 | | .WithPortBinding(6055) |
| | 12 | 62 | | .WithPortBinding(6056) |
| | 12 | 63 | | .WithPortBinding(6057) |
| | 12 | 64 | | .WithPortBinding(6058) |
| | 12 | 65 | | .WithPortBinding(6059) |
| | 12 | 66 | | .WithPortBinding(6060) |
| | 12 | 67 | | .WithExtraHost("buildkitsandbox", "127.0.0.1") |
| | 12 | 68 | | .WithWaitStrategy( |
| | 12 | 69 | | Wait.ForUnixContainer() |
| | 12 | 70 | | .UntilExternalTcpPortIsAvailable(6030, strategy => strategy.WithTimeout(TimeSpan.FromSeconds(15) |
| | 12 | 71 | | ) |
| | 12 | 72 | | .Build(); |
| | | 73 | | |
| | | 74 | | // Start the container. |
| | | 75 | | try |
| | 12 | 76 | | { |
| | 12 | 77 | | Task tdEngineStartAsync = tdEngineContainer.StartAsync(); |
| | 12 | 78 | | await tdEngineStartAsync.WaitAsync(TimeSpan.FromSeconds(30)); |
| | | 79 | | // Wait to make sure the processes in container are ready and running. |
| | 12 | 80 | | await WaitForTDengineToBeReady(); |
| | 12 | 81 | | Console.WriteLine("TD engine container started"); |
| | 12 | 82 | | } |
| | 0 | 83 | | catch (Exception) |
| | 0 | 84 | | { |
| | 0 | 85 | | await StopTDengineContainerAsync(); |
| | 0 | 86 | | throw; |
| | | 87 | | } |
| | | 88 | | } |
| | 12 | 89 | | return $"host={tdEngineContainer.Hostname};port={tdEngineContainer.GetMappedPublicPort(6030)};username=root; |
| | 12 | 90 | | } |
| | | 91 | | |
| | | 92 | | private async ValueTask WaitForTDengineToBeReady() |
| | 12 | 93 | | { |
| | 12 | 94 | | bool connected = false; |
| | 12 | 95 | | int index = 0; |
| | 48 | 96 | | while (!connected && index < 10) |
| | 36 | 97 | | { |
| | 36 | 98 | | SystemCommand.Run("taos", $"-h {tdEngineContainer!.Hostname} -P {tdEngineContainer.GetMappedPublicPort(6 |
| | 36 | 99 | | connected = output.Contains("ready"); |
| | 36 | 100 | | if (!connected) |
| | 24 | 101 | | { |
| | 24 | 102 | | Thread.Sleep(500); |
| | 24 | 103 | | index++; |
| | 24 | 104 | | } |
| | 36 | 105 | | } |
| | 12 | 106 | | if (!connected) |
| | 0 | 107 | | { |
| | 0 | 108 | | var (Stdout, Stderr) = await tdEngineContainer!.GetLogsAsync(); |
| | 0 | 109 | | throw new ApplicationException($"Can't connect to TDengine container {tdEngineContainer!.Hostname}! Out: |
| | | 110 | | } |
| | 12 | 111 | | } |
| | | 112 | | |
| | | 113 | | public async Task<long> StopTDengineContainerAsync() |
| | 146 | 114 | | { |
| | 146 | 115 | | if (tdEngineContainer is not null) |
| | 12 | 116 | | { |
| | 12 | 117 | | await tdEngineContainer.StopAsync(); |
| | 12 | 118 | | Console.WriteLine($"TD engine container {tdEngineContainer.Id} stopped"); |
| | 12 | 119 | | long exitCode = await tdEngineContainer.GetExitCodeAsync(); |
| | 12 | 120 | | Console.WriteLine($"TD engine container {tdEngineContainer.Id} exit code {exitCode}"); |
| | 12 | 121 | | tdEngineContainer = null; |
| | 12 | 122 | | return exitCode; |
| | | 123 | | } |
| | 134 | 124 | | return 0; |
| | 146 | 125 | | } |
| | | 126 | | |
| | | 127 | | protected virtual async ValueTask DisposeAsync(bool disposing) |
| | 0 | 128 | | { |
| | 0 | 129 | | if (!disposedValue) |
| | 0 | 130 | | { |
| | 0 | 131 | | await StopTDengineContainerAsync(); |
| | 0 | 132 | | disposedValue = true; |
| | 0 | 133 | | } |
| | 0 | 134 | | } |
| | | 135 | | |
| | | 136 | | public async ValueTask DisposeAsync() |
| | 0 | 137 | | { |
| | | 138 | | // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method |
| | 0 | 139 | | await DisposeAsync(disposing: true); |
| | 0 | 140 | | GC.SuppressFinalize(this); |
| | 0 | 141 | | } |
| | | 142 | | } |
| | | 143 | | } |