|
1 | 1 | using System;
|
2 |
| -using System.Diagnostics; |
3 |
| -using System.Net.Http; |
| 2 | +using System.Collections.Generic; |
| 3 | +using System.Linq; |
4 | 4 | using System.Threading.Tasks;
|
| 5 | +using Ductus.FluentDocker.Builders; |
| 6 | +using Ductus.FluentDocker.Model.Common; |
| 7 | +using Ductus.FluentDocker.Services; |
| 8 | +using Ductus.FluentDocker.Services.Extensions; |
| 9 | +using FluentAssertions; |
5 | 10 | using Xunit;
|
6 | 11 |
|
7 | 12 | namespace GitLabApiClient.Test.Utilities
|
8 | 13 | {
|
9 | 14 | public class GitLabContainerFixture : IAsyncLifetime
|
10 | 15 | {
|
11 |
| - private const string GitLabContainerPath = "../../../../docker"; |
| 16 | + private const string InitRb = "/tmp/init.rb"; |
| 17 | + private const string GitlabRb = "/tmp/gitlab.rb"; |
| 18 | + private static readonly TemplateString SolutionRootFolder = "${PWD}/../../../../.."; |
12 | 19 |
|
13 |
| - private const string GitLabApiPath = "http://localhost:9190/"; |
| 20 | + public static string Token { get; private set; } |
| 21 | + public static string GitlabHost { get; private set; } |
14 | 22 |
|
15 |
| - private static readonly TimeSpan TestTimeout = TimeSpan.FromMinutes(10); |
16 |
| - |
17 |
| - private HttpClient _gitLabPingClient; |
| 23 | + private IContainerService _gitlabContainer; |
| 24 | + private readonly string _gitlabDockerImage = "gitlab/gitlab-ce:12.5.4-ce.0"; |
18 | 25 |
|
19 | 26 | public async Task InitializeAsync()
|
20 | 27 | {
|
21 |
| - _gitLabPingClient = new HttpClient |
22 |
| - { |
23 |
| - Timeout = TimeSpan.FromSeconds(1) |
24 |
| - }; |
25 |
| - |
26 |
| - StartContainer(); |
27 |
| - if (!await WaitForService()) |
28 |
| - throw new Exception("Failed to start container, timeout hit."); |
| 28 | + await StartContainer(); |
| 29 | + Token = InitializeData(); |
| 30 | + string hostAndPort = GetContainerHostPort(_gitlabContainer, "80/tcp"); |
| 31 | + GitlabHost = $"http://{hostAndPort}/api/v4/"; |
29 | 32 | }
|
30 | 33 |
|
31 |
| - public Task DisposeAsync() |
| 34 | + public async Task DisposeAsync() |
32 | 35 | {
|
33 |
| - StopContainer(); |
34 |
| - return Task.CompletedTask; |
| 36 | + await StopContainer(); |
35 | 37 | }
|
36 | 38 |
|
37 |
| - private void StartContainer() |
| 39 | + private Task StartContainer() |
38 | 40 | {
|
39 |
| - StartProcessAndWaitForExit(new ProcessStartInfo |
40 |
| - { |
41 |
| - FileName = "docker-compose", |
42 |
| - Arguments = |
43 |
| - $"-f {GitLabContainerPath}/docker-compose.yml up -d" |
44 |
| - }); |
| 41 | + _gitlabContainer = new Builder() |
| 42 | + .UseContainer() |
| 43 | + .UseImage(_gitlabDockerImage) |
| 44 | + .WithEnvironment( |
| 45 | + $"GITLAB_OMNIBUS_CONFIG=from_file('{GitlabRb}')" |
| 46 | + ) |
| 47 | + .ExposePort(80) |
| 48 | + .CopyOnStart($"{SolutionRootFolder}/docker/gitlab.rb", GitlabRb) |
| 49 | + .CopyOnStart($"{SolutionRootFolder}/docker/init.rb", InitRb) |
| 50 | + .WaitForHealthy() |
| 51 | + .Build() |
| 52 | + .Start(); |
| 53 | + |
| 54 | + return Task.CompletedTask; |
45 | 55 | }
|
46 | 56 |
|
47 |
| - private void StopContainer() |
| 57 | + private Task StopContainer() |
48 | 58 | {
|
49 |
| - var processStartInfo = new ProcessStartInfo |
50 |
| - { |
51 |
| - FileName = "docker-compose", |
52 |
| - Arguments = |
53 |
| - $"-f {GitLabContainerPath}/docker-compose.yml down" |
54 |
| - }; |
| 59 | + _gitlabContainer?.Stop(); |
| 60 | + _gitlabContainer?.Dispose(); |
55 | 61 |
|
56 |
| - StartProcessAndWaitForExit(processStartInfo); |
| 62 | + return Task.CompletedTask; |
57 | 63 | }
|
58 | 64 |
|
59 |
| - private void StartProcessAndWaitForExit(ProcessStartInfo processStartInfo) |
| 65 | + private string InitializeData() |
60 | 66 | {
|
61 |
| - processStartInfo.UseShellExecute = false; |
62 |
| - processStartInfo.RedirectStandardOutput = true; |
63 |
| - processStartInfo.CreateNoWindow = true; |
64 |
| - processStartInfo.Environment["COMPUTERNAME"] = Environment.MachineName; |
65 |
| - |
66 |
| - var process = new Process |
67 |
| - { |
68 |
| - StartInfo = processStartInfo |
69 |
| - }; |
70 |
| - |
71 |
| - process.OutputDataReceived += LogOutputData; |
72 |
| - process.Start(); |
73 |
| - process.BeginOutputReadLine(); |
74 |
| - process.WaitForExit(); |
75 |
| - |
76 |
| - Assert.Equal(0, process.ExitCode); |
77 |
| - |
78 |
| - void LogOutputData(object sender, DataReceivedEventArgs e) |
79 |
| - //TODO: find out how to log data in XUnit fixtures |
80 |
| - => Trace.WriteLine(e.Data); |
| 67 | + string command = $"/opt/gitlab/bin/gitlab-rails r {InitRb}"; |
| 68 | + var output = ExecuteCommandAgainstDockerWithOutput(_gitlabContainer, command); |
| 69 | + string token = output.FirstOrDefault(); |
| 70 | + token.Should().NotBeNullOrEmpty(); |
| 71 | + return token; |
81 | 72 | }
|
82 | 73 |
|
83 |
| - private async Task<bool> WaitForService() |
| 74 | + private static IEnumerable<string> ExecuteCommandAgainstDockerWithOutput(IContainerService container, string command) |
84 | 75 | {
|
85 |
| - var startTime = DateTime.Now; |
| 76 | + var output = container.Execute(command); |
| 77 | + string error = output.Error; |
| 78 | + error.Should().BeEmpty(); |
| 79 | + output.Success.Should().BeTrue(); |
| 80 | + output.Data.Should().NotBeNullOrEmpty(); |
86 | 81 |
|
87 |
| - while (DateTime.Now - startTime < TestTimeout) |
88 |
| - { |
89 |
| - try |
90 |
| - { |
91 |
| - var response = await _gitLabPingClient.GetAsync(GitLabApiPath); |
92 |
| - if (response.IsSuccessStatusCode) |
93 |
| - { |
94 |
| - Trace.WriteLine("GitLab started to respond!"); |
95 |
| - return true; |
96 |
| - } |
97 |
| - } |
98 |
| - catch (HttpRequestException) |
99 |
| - { |
100 |
| - } |
101 |
| - catch (OperationCanceledException) |
102 |
| - { |
103 |
| - } |
104 |
| - |
105 |
| - await Task.Delay(15000); |
106 |
| - } |
| 82 | + return output.Data; |
| 83 | + } |
107 | 84 |
|
108 |
| - return false; |
| 85 | + private static string GetContainerHostPort(IContainerService containerService, string portAndProto) |
| 86 | + { |
| 87 | + var ep = containerService.ToHostExposedEndpoint(portAndProto); |
| 88 | + string hostAndPort = $"localhost:{ep.Port}"; |
| 89 | + return hostAndPort; |
109 | 90 | }
|
110 | 91 | }
|
111 | 92 | }
|
0 commit comments