From 99373378b40ea49cb7129bce46a5208f975486e0 Mon Sep 17 00:00:00 2001
From: Peet-HD <19489992+Peet-HD@users.noreply.github.com>
Date: Mon, 4 Mar 2024 00:44:42 +0000
Subject: [PATCH 1/7] Added Gitlab Container to test against the gitlab API.
---
Testcontainers.sln | 9 +-
src/Testcontainers.Gitlab/.editorconfig | 1 +
src/Testcontainers.Gitlab/GitlabBuilder.cs | 78 +++++++++++++++
.../GitlabConfiguration.cs | 53 +++++++++++
src/Testcontainers.Gitlab/GitlabContainer.cs | 95 +++++++++++++++++++
.../Models/PersonalAccessToken.cs | 11 +++
.../Models/PersonalAccessTokenScopes.cs | 18 ++++
.../RegexPatterns/GitlabRegex.cs | 18 ++++
.../Testcontainers.Gitlab.csproj | 12 +++
src/Testcontainers.Gitlab/Usings.cs | 15 +++
10 files changed, 309 insertions(+), 1 deletion(-)
create mode 100644 src/Testcontainers.Gitlab/.editorconfig
create mode 100644 src/Testcontainers.Gitlab/GitlabBuilder.cs
create mode 100644 src/Testcontainers.Gitlab/GitlabConfiguration.cs
create mode 100644 src/Testcontainers.Gitlab/GitlabContainer.cs
create mode 100644 src/Testcontainers.Gitlab/Models/PersonalAccessToken.cs
create mode 100644 src/Testcontainers.Gitlab/Models/PersonalAccessTokenScopes.cs
create mode 100644 src/Testcontainers.Gitlab/RegexPatterns/GitlabRegex.cs
create mode 100644 src/Testcontainers.Gitlab/Testcontainers.Gitlab.csproj
create mode 100644 src/Testcontainers.Gitlab/Usings.cs
diff --git a/Testcontainers.sln b/Testcontainers.sln
index 9595905ed..36d85e98b 100644
--- a/Testcontainers.sln
+++ b/Testcontainers.sln
@@ -1,4 +1,4 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
+Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
@@ -195,6 +195,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Tests", "tes
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.WebDriver.Tests", "tests\Testcontainers.WebDriver.Tests\Testcontainers.WebDriver.Tests.csproj", "{EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Gitlab", "src\Testcontainers.Gitlab\Testcontainers.Gitlab.csproj", "{B3857615-7DD1-41D2-BA74-938DA4469E5E}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -568,6 +570,10 @@ Global
{EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B3857615-7DD1-41D2-BA74-938DA4469E5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B3857615-7DD1-41D2-BA74-938DA4469E5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B3857615-7DD1-41D2-BA74-938DA4469E5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B3857615-7DD1-41D2-BA74-938DA4469E5E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{5365F780-0E6C-41F0-B1B9-7DC34368F80C} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
@@ -661,5 +667,6 @@ Global
{1A1983E6-5297-435F-B467-E8E1F11277D6} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{27CDB869-A150-4593-958F-6F26E5391E7C} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
+ {B3857615-7DD1-41D2-BA74-938DA4469E5E} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
EndGlobalSection
EndGlobal
diff --git a/src/Testcontainers.Gitlab/.editorconfig b/src/Testcontainers.Gitlab/.editorconfig
new file mode 100644
index 000000000..6f066619d
--- /dev/null
+++ b/src/Testcontainers.Gitlab/.editorconfig
@@ -0,0 +1 @@
+root = true
\ No newline at end of file
diff --git a/src/Testcontainers.Gitlab/GitlabBuilder.cs b/src/Testcontainers.Gitlab/GitlabBuilder.cs
new file mode 100644
index 000000000..9996ab4d0
--- /dev/null
+++ b/src/Testcontainers.Gitlab/GitlabBuilder.cs
@@ -0,0 +1,78 @@
+ namespace Testcontainers.Gitlab;
+
+ ///
+ [PublicAPI]
+ public sealed class GitlabBuilder : ContainerBuilder
+ {
+ ///
+ /// This is the default image for gitlab community edition.
+ ///
+ public const string GitlabImage = "gitlab/gitlab-ce";
+ ///
+ /// This port is used for http communication to gitlab instance.
+ ///
+
+ public const ushort GitlabHttpPort = 80;
+ ///
+ /// This port is used for ssh communication to gitlab instance.
+ ///
+ public const ushort GitlabSshPort = 22;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public GitlabBuilder()
+ : this(new GitlabConfiguration())
+ {
+ DockerResourceConfiguration = Init().DockerResourceConfiguration;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Docker resource configuration.
+ private GitlabBuilder(GitlabConfiguration resourceConfiguration)
+ : base(resourceConfiguration)
+ {
+ DockerResourceConfiguration = resourceConfiguration;
+ }
+
+ ///
+ protected override GitlabConfiguration DockerResourceConfiguration { get; }
+
+ ///
+ public override GitlabContainer Build()
+ {
+ Validate();
+ return new GitlabContainer(DockerResourceConfiguration, TestcontainersSettings.Logger);
+ }
+
+ ///
+ protected override GitlabBuilder Init()
+ {
+ return base.Init()
+ .WithImage(GitlabImage)
+ .WithPortBinding(GitlabHttpPort, true)
+ .WithPortBinding(GitlabSshPort, true)
+ .WithWaitStrategy(Wait.ForUnixContainer().UntilFileExists("/etc/gitlab/initial_root_password"))
+ .WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(80))
+ .WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(22))
+ .WithWaitStrategy(Wait.ForUnixContainer().UntilContainerIsHealthy())
+ .WithWaitStrategy(Wait.ForUnixContainer().UntilHttpRequestIsSucceeded(request => request.ForPath("/users/sign_in").ForStatusCode(HttpStatusCode.OK)));
+ }
+
+ ///
+ protected override void Validate() => base.Validate();
+
+ ///
+ protected override GitlabBuilder Clone(IResourceConfiguration resourceConfiguration)
+ => Merge(DockerResourceConfiguration, new GitlabConfiguration(resourceConfiguration));
+
+ ///
+ protected override GitlabBuilder Clone(IContainerConfiguration resourceConfiguration)
+ => Merge(DockerResourceConfiguration, new GitlabConfiguration(resourceConfiguration));
+
+ ///
+ protected override GitlabBuilder Merge(GitlabConfiguration oldValue, GitlabConfiguration newValue)
+ => new(new GitlabConfiguration(oldValue, newValue));
+ }
\ No newline at end of file
diff --git a/src/Testcontainers.Gitlab/GitlabConfiguration.cs b/src/Testcontainers.Gitlab/GitlabConfiguration.cs
new file mode 100644
index 000000000..64e73b523
--- /dev/null
+++ b/src/Testcontainers.Gitlab/GitlabConfiguration.cs
@@ -0,0 +1,53 @@
+namespace Testcontainers.Gitlab;
+
+ ///
+ [PublicAPI]
+ public sealed class GitlabConfiguration : ContainerConfiguration
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public GitlabConfiguration()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Docker resource configuration.
+ public GitlabConfiguration(IResourceConfiguration resourceConfiguration)
+ : base(resourceConfiguration)
+ {
+ // Passes the configuration upwards to the base implementations to create an updated immutable copy.
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Docker resource configuration.
+ public GitlabConfiguration(IContainerConfiguration resourceConfiguration)
+ : base(resourceConfiguration)
+ {
+ // Passes the configuration upwards to the base implementations to create an updated immutable copy.
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Docker resource configuration.
+ public GitlabConfiguration(GitlabConfiguration resourceConfiguration)
+ : this(new GitlabConfiguration(), resourceConfiguration)
+ {
+ // Passes the configuration upwards to the base implementations to create an updated immutable copy.
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The old Docker resource configuration.
+ /// The new Docker resource configuration.
+ public GitlabConfiguration(GitlabConfiguration oldValue, GitlabConfiguration newValue)
+ : base(oldValue, newValue)
+ {
+ }
+ }
\ No newline at end of file
diff --git a/src/Testcontainers.Gitlab/GitlabContainer.cs b/src/Testcontainers.Gitlab/GitlabContainer.cs
new file mode 100644
index 000000000..0551c58ed
--- /dev/null
+++ b/src/Testcontainers.Gitlab/GitlabContainer.cs
@@ -0,0 +1,95 @@
+using Testcontainers.Gitlab.Models;
+using Testcontainers.Gitlab.RegexPatterns;
+
+namespace Testcontainers.Gitlab
+{
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The container configuration.
+ /// The logger.
+ [PublicAPI]
+ public sealed class GitlabContainer(GitlabConfiguration configuration, ILogger logger) : DockerContainer(configuration, logger)
+ {
+ ///
+ /// The password for the root user
+ ///
+ public string RootPassword { get; private set; }
+
+ public override async Task StartAsync(CancellationToken ct = default)
+ {
+ await base.StartAsync(ct);
+ RootPassword = await GetInitialRootPassword();
+ }
+
+ ///
+ /// Generate a personal access token.
+ ///
+ /// The personal access token to create.
+ ///
+ ///
+ public async Task GenerateAccessToken(PersonalAccessToken pat)
+ {
+ var scope = "[" + '\'' + pat.Scope.ToString().Replace(", ", "\', \'") + '\'' + "]";
+
+ var command = $"token = User.find_by_username('{pat.User}')" +
+ $".personal_access_tokens" +
+ $".create(name: '{pat.Name}', scopes: {scope}, expires_at: {pat.ExpirationInDays}.days.from_now); " +
+ $"puts token.cleartext_tokens";
+
+ var tokenCommand = new List{
+ { "gitlab-rails" },
+ { "runner" },
+ { command }
+ };
+
+ ExecResult tokenResult = await ExecAsync(tokenCommand);
+
+ string token = "";
+ if (tokenResult.ExitCode == 0)
+ {
+ var match = GitlabRegex.GitlabPersonalAccessToken.Match(tokenResult.Stdout);
+ token = match.Value;
+ }
+ else
+ {
+ throw new DataMisalignedException("Stderr: " + tokenResult.Stderr + "|" + "Stdout: " + tokenResult.Stdout);
+ }
+ pat.TokenInternal = token;
+ return pat;
+ }
+
+ ///
+ /// Generate a personal access token.
+ ///
+ /// Name of
+ ///
+ ///
+ ///
+ ///
+ public async Task GenerateAccessToken(string user, PersonalAccessTokenScopes scope, string name = "", int expirationInDays = 365)
+ => await GenerateAccessToken(new PersonalAccessToken
+ {
+ Name = string.IsNullOrWhiteSpace(name) ? Guid.NewGuid().ToString() : name,
+ User = user,
+ Scope = scope,
+ ExpirationInDays = expirationInDays
+ });
+
+
+ ///
+ /// This method returns the initial root password for the gitlab root user.
+ ///
+ /// Returns the initial root password generated by gitlab.
+ private async Task GetInitialRootPassword()
+ {
+ var byteArray = await ReadFileAsync("/etc/gitlab/initial_root_password");
+
+ string fileContent = Encoding.UTF8.GetString(byteArray);
+ var match = GitlabRegex.GitlabRootPassword.Match(fileContent);
+ string[] splits = match.Value.Split(' ');
+ return splits[1];
+ }
+}
+}
\ No newline at end of file
diff --git a/src/Testcontainers.Gitlab/Models/PersonalAccessToken.cs b/src/Testcontainers.Gitlab/Models/PersonalAccessToken.cs
new file mode 100644
index 000000000..e64e52087
--- /dev/null
+++ b/src/Testcontainers.Gitlab/Models/PersonalAccessToken.cs
@@ -0,0 +1,11 @@
+namespace Testcontainers.Gitlab.Models;
+
+public record PersonalAccessToken
+{
+ public string Name { get; set; } = string.Empty;
+ public string User { get; set; } = string.Empty;
+ public PersonalAccessTokenScopes Scope { get; set; } = PersonalAccessTokenScopes.None;
+ public int ExpirationInDays { get; set; } = 365;
+ internal string TokenInternal { get; set; } = string.Empty;
+ public string Token => TokenInternal;
+}
diff --git a/src/Testcontainers.Gitlab/Models/PersonalAccessTokenScopes.cs b/src/Testcontainers.Gitlab/Models/PersonalAccessTokenScopes.cs
new file mode 100644
index 000000000..2bf72803e
--- /dev/null
+++ b/src/Testcontainers.Gitlab/Models/PersonalAccessTokenScopes.cs
@@ -0,0 +1,18 @@
+namespace Testcontainers.Gitlab.Models
+{
+ [Flags]
+ public enum PersonalAccessTokenScopes
+ {
+ None = 0,
+ api = 2,
+ read_api = 4,
+ read_user = 8,
+ read_repository = 16,
+ write_repository = 32,
+ read_registry = 64,
+ write_registry = 128,
+ create_runner = 256,
+ ai_features = 512,
+ k8s_proxy = 1024,
+ }
+}
\ No newline at end of file
diff --git a/src/Testcontainers.Gitlab/RegexPatterns/GitlabRegex.cs b/src/Testcontainers.Gitlab/RegexPatterns/GitlabRegex.cs
new file mode 100644
index 000000000..378965f8e
--- /dev/null
+++ b/src/Testcontainers.Gitlab/RegexPatterns/GitlabRegex.cs
@@ -0,0 +1,18 @@
+using System.Text.RegularExpressions;
+
+namespace Testcontainers.Gitlab.RegexPatterns;
+
+///
+/// This class contains regex patterns that are used in gitlab.
+///
+public static partial class GitlabRegex
+{
+ ///
+ /// GitLab Personal Access Token
+ ///
+ public static Regex GitlabPersonalAccessToken => new(@"glpat-[0-9a-zA-Z_\-]{20}", RegexOptions.Compiled | RegexOptions.IgnoreCase);
+ ///
+ /// Regex Pattern to find the gitlab root password
+ ///
+ public static Regex GitlabRootPassword => new(@"Password: .*", RegexOptions.Compiled | RegexOptions.IgnoreCase);
+}
\ No newline at end of file
diff --git a/src/Testcontainers.Gitlab/Testcontainers.Gitlab.csproj b/src/Testcontainers.Gitlab/Testcontainers.Gitlab.csproj
new file mode 100644
index 000000000..8b2ed72c6
--- /dev/null
+++ b/src/Testcontainers.Gitlab/Testcontainers.Gitlab.csproj
@@ -0,0 +1,12 @@
+
+
+ net6.0;net8.0;netstandard2.0;netstandard2.1
+ latest
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Testcontainers.Gitlab/Usings.cs b/src/Testcontainers.Gitlab/Usings.cs
new file mode 100644
index 000000000..0e135aab0
--- /dev/null
+++ b/src/Testcontainers.Gitlab/Usings.cs
@@ -0,0 +1,15 @@
+global using System;
+global using System.Collections.Generic;
+global using System.IO;
+global using System.Net;
+global using System.Linq;
+global using System.Text;
+global using System.Threading;
+global using System.Threading.Tasks;
+global using Docker.DotNet.Models;
+global using DotNet.Testcontainers;
+global using DotNet.Testcontainers.Builders;
+global using DotNet.Testcontainers.Configurations;
+global using DotNet.Testcontainers.Containers;
+global using JetBrains.Annotations;
+global using Microsoft.Extensions.Logging;
\ No newline at end of file
From ef082600d80e1c26e03d5b6aa12ec606dab549d3 Mon Sep 17 00:00:00 2001
From: Peet-HD <19489992+Peet-HD@users.noreply.github.com>
Date: Mon, 4 Mar 2024 09:35:57 +0000
Subject: [PATCH 2/7] Improved documentation
---
src/Testcontainers.Gitlab/GitlabContainer.cs | 153 +++++++++---------
.../Models/PersonalAccessToken.cs | 25 +++
2 files changed, 101 insertions(+), 77 deletions(-)
diff --git a/src/Testcontainers.Gitlab/GitlabContainer.cs b/src/Testcontainers.Gitlab/GitlabContainer.cs
index 0551c58ed..ba9b02e55 100644
--- a/src/Testcontainers.Gitlab/GitlabContainer.cs
+++ b/src/Testcontainers.Gitlab/GitlabContainer.cs
@@ -1,95 +1,94 @@
using Testcontainers.Gitlab.Models;
using Testcontainers.Gitlab.RegexPatterns;
-namespace Testcontainers.Gitlab
+namespace Testcontainers.Gitlab;
+
+///
+///
+/// Initializes a new instance of the class.
+///
+/// The container configuration.
+/// The logger.
+[PublicAPI]
+public sealed class GitlabContainer(GitlabConfiguration configuration, ILogger logger) : DockerContainer(configuration, logger)
{
- ///
///
- /// Initializes a new instance of the class.
+ /// The password for the root user
///
- /// The container configuration.
- /// The logger.
- [PublicAPI]
- public sealed class GitlabContainer(GitlabConfiguration configuration, ILogger logger) : DockerContainer(configuration, logger)
- {
- ///
- /// The password for the root user
- ///
- public string RootPassword { get; private set; }
+ public string RootPassword { get; private set; }
- public override async Task StartAsync(CancellationToken ct = default)
- {
- await base.StartAsync(ct);
- RootPassword = await GetInitialRootPassword();
- }
+ public override async Task StartAsync(CancellationToken ct = default)
+ {
+ await base.StartAsync(ct);
+ RootPassword = await GetInitialRootPassword();
+ }
- ///
- /// Generate a personal access token.
- ///
- /// The personal access token to create.
- ///
- ///
- public async Task GenerateAccessToken(PersonalAccessToken pat)
- {
- var scope = "[" + '\'' + pat.Scope.ToString().Replace(", ", "\', \'") + '\'' + "]";
+ ///
+ /// Generate a personal access token.
+ ///
+ /// The personal access token to create.
+ ///
+ ///
+ public async Task GenerateAccessToken(PersonalAccessToken pat)
+ {
+ var scope = "[" + '\'' + pat.Scope.ToString().Replace(", ", "\', \'") + '\'' + "]";
- var command = $"token = User.find_by_username('{pat.User}')" +
- $".personal_access_tokens" +
- $".create(name: '{pat.Name}', scopes: {scope}, expires_at: {pat.ExpirationInDays}.days.from_now); " +
- $"puts token.cleartext_tokens";
+ var command = $"token = User.find_by_username('{pat.User}')" +
+ $".personal_access_tokens" +
+ $".create(name: '{pat.Name}', scopes: {scope}, expires_at: {pat.ExpirationInDays}.days.from_now); " +
+ $"puts token.cleartext_tokens";
- var tokenCommand = new List{
- { "gitlab-rails" },
- { "runner" },
- { command }
- };
+ var tokenCommand = new List{
+ { "gitlab-rails" },
+ { "runner" },
+ { command }
+ };
- ExecResult tokenResult = await ExecAsync(tokenCommand);
+ ExecResult tokenResult = await ExecAsync(tokenCommand);
- string token = "";
- if (tokenResult.ExitCode == 0)
- {
- var match = GitlabRegex.GitlabPersonalAccessToken.Match(tokenResult.Stdout);
- token = match.Value;
- }
- else
- {
- throw new DataMisalignedException("Stderr: " + tokenResult.Stderr + "|" + "Stdout: " + tokenResult.Stdout);
- }
- pat.TokenInternal = token;
- return pat;
+ string token = "";
+ if (tokenResult.ExitCode == 0)
+ {
+ var match = GitlabRegex.GitlabPersonalAccessToken.Match(tokenResult.Stdout);
+ token = match.Value;
}
+ else
+ {
+ throw new DataMisalignedException("Stderr: " + tokenResult.Stderr + "|" + "Stdout: " + tokenResult.Stdout);
+ }
+ pat.TokenInternal = token;
+ return pat;
+ }
- ///
- /// Generate a personal access token.
- ///
- /// Name of
- ///
- ///
- ///
- ///
- public async Task GenerateAccessToken(string user, PersonalAccessTokenScopes scope, string name = "", int expirationInDays = 365)
- => await GenerateAccessToken(new PersonalAccessToken
- {
- Name = string.IsNullOrWhiteSpace(name) ? Guid.NewGuid().ToString() : name,
- User = user,
- Scope = scope,
- ExpirationInDays = expirationInDays
- });
+ ///
+ /// Generate a personal access token.
+ ///
+ /// Name of the personal access token. If left empty a GUID will be used.
+ /// The name of the user that owns this personal access token.
+ /// The scope that will be given to the token.
+ /// Days until the tokens expires.
+ ///
+ public async Task GenerateAccessToken(string user, PersonalAccessTokenScopes scope, string name = "", int expirationInDays = 365)
+ => await GenerateAccessToken(new PersonalAccessToken
+ {
+ Name = string.IsNullOrWhiteSpace(name) ? Guid.NewGuid().ToString() : name,
+ User = user,
+ Scope = scope,
+ ExpirationInDays = expirationInDays
+ });
- ///
- /// This method returns the initial root password for the gitlab root user.
- ///
- /// Returns the initial root password generated by gitlab.
- private async Task GetInitialRootPassword()
- {
- var byteArray = await ReadFileAsync("/etc/gitlab/initial_root_password");
+ ///
+ /// This method returns the initial root password for the gitlab root user.
+ ///
+ /// Returns the initial root password generated by gitlab.
+ private async Task GetInitialRootPassword()
+ {
+ var byteArray = await ReadFileAsync("/etc/gitlab/initial_root_password");
- string fileContent = Encoding.UTF8.GetString(byteArray);
- var match = GitlabRegex.GitlabRootPassword.Match(fileContent);
- string[] splits = match.Value.Split(' ');
- return splits[1];
- }
-}
+ string fileContent = Encoding.UTF8.GetString(byteArray);
+ var match = GitlabRegex.GitlabRootPassword.Match(fileContent);
+ string[] splits = match.Value.Split(' ');
+ return splits[1];
+ }
}
\ No newline at end of file
diff --git a/src/Testcontainers.Gitlab/Models/PersonalAccessToken.cs b/src/Testcontainers.Gitlab/Models/PersonalAccessToken.cs
index e64e52087..0c7d53576 100644
--- a/src/Testcontainers.Gitlab/Models/PersonalAccessToken.cs
+++ b/src/Testcontainers.Gitlab/Models/PersonalAccessToken.cs
@@ -1,11 +1,36 @@
namespace Testcontainers.Gitlab.Models;
+///
+/// The personal access token that is used to authenticate against the API from gitlab.
+///
public record PersonalAccessToken
{
+ /// Name of the personal access token. If left empty a GUID will be used.
+ /// The name of the user that owns this personal access token.
+ /// The scope that will be given to the token.
+ /// Days until the tokens expires.
+ ///
+ /// Name of the personal access token. If left empty a GUID will be used.
+ ///
public string Name { get; set; } = string.Empty;
+ ///
+ /// The name of the user that owns this personal access token.
+ ///
public string User { get; set; } = string.Empty;
+ ///
+ /// The scope that will be given to the token.
+ ///
public PersonalAccessTokenScopes Scope { get; set; } = PersonalAccessTokenScopes.None;
+ ///
+ /// Days until the tokens expires.
+ ///
public int ExpirationInDays { get; set; } = 365;
+ ///
+ /// Internal token that is used to set the token publically.
+ ///
internal string TokenInternal { get; set; } = string.Empty;
+ ///
+ /// The token that will be generated.
+ ///
public string Token => TokenInternal;
}
From 5c4e69d56d7cd89fadc634e5fccbc0125e1e6983 Mon Sep 17 00:00:00 2001
From: Peet-HD <19489992+Peet-HD@users.noreply.github.com>
Date: Mon, 4 Mar 2024 16:47:58 +0000
Subject: [PATCH 3/7] Add test project for gitlab
---
Testcontainers.sln | 7 +++++
.../Testcontainers.Gitlab.Tests/.editorconfig | 1 +
.../GitlabContainerTests.cs | 29 +++++++++++++++++++
.../Testcontainers.Gitlab.Tests.csproj | 18 ++++++++++++
tests/Testcontainers.Gitlab.Tests/Usings.cs | 6 ++++
5 files changed, 61 insertions(+)
create mode 100644 tests/Testcontainers.Gitlab.Tests/.editorconfig
create mode 100644 tests/Testcontainers.Gitlab.Tests/GitlabContainerTests.cs
create mode 100644 tests/Testcontainers.Gitlab.Tests/Testcontainers.Gitlab.Tests.csproj
create mode 100644 tests/Testcontainers.Gitlab.Tests/Usings.cs
diff --git a/Testcontainers.sln b/Testcontainers.sln
index 36d85e98b..e0c1aaee9 100644
--- a/Testcontainers.sln
+++ b/Testcontainers.sln
@@ -197,6 +197,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.WebDriver.Te
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Gitlab", "src\Testcontainers.Gitlab\Testcontainers.Gitlab.csproj", "{B3857615-7DD1-41D2-BA74-938DA4469E5E}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Gitlab.Tests", "tests\Testcontainers.Gitlab.Tests\Testcontainers.Gitlab.Tests.csproj", "{185C65BB-0F79-40D0-A940-7CBE7C8E6A30}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -574,6 +576,10 @@ Global
{B3857615-7DD1-41D2-BA74-938DA4469E5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B3857615-7DD1-41D2-BA74-938DA4469E5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B3857615-7DD1-41D2-BA74-938DA4469E5E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {185C65BB-0F79-40D0-A940-7CBE7C8E6A30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {185C65BB-0F79-40D0-A940-7CBE7C8E6A30}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {185C65BB-0F79-40D0-A940-7CBE7C8E6A30}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {185C65BB-0F79-40D0-A940-7CBE7C8E6A30}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{5365F780-0E6C-41F0-B1B9-7DC34368F80C} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
@@ -668,5 +674,6 @@ Global
{27CDB869-A150-4593-958F-6F26E5391E7C} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{B3857615-7DD1-41D2-BA74-938DA4469E5E} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
+ {185C65BB-0F79-40D0-A940-7CBE7C8E6A30} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
EndGlobalSection
EndGlobal
diff --git a/tests/Testcontainers.Gitlab.Tests/.editorconfig b/tests/Testcontainers.Gitlab.Tests/.editorconfig
new file mode 100644
index 000000000..6f066619d
--- /dev/null
+++ b/tests/Testcontainers.Gitlab.Tests/.editorconfig
@@ -0,0 +1 @@
+root = true
\ No newline at end of file
diff --git a/tests/Testcontainers.Gitlab.Tests/GitlabContainerTests.cs b/tests/Testcontainers.Gitlab.Tests/GitlabContainerTests.cs
new file mode 100644
index 000000000..f1d388c62
--- /dev/null
+++ b/tests/Testcontainers.Gitlab.Tests/GitlabContainerTests.cs
@@ -0,0 +1,29 @@
+using Testcontainers.Gitlab.Models;
+using Testcontainers.Gitlab.RegexPatterns;
+using System.Net.Http;
+using System;
+
+namespace Testcontainers.Gitlab;
+
+public sealed class GitlabContainerTest : IAsyncLifetime
+{
+ private readonly GitlabContainer _gitlabContainer = new GitlabBuilder().Build();
+
+ public Task InitializeAsync()
+ {
+ return _gitlabContainer.StartAsync();
+ }
+
+ public Task DisposeAsync()
+ {
+ return _gitlabContainer.DisposeAsync().AsTask();
+ }
+
+ [Fact]
+ [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
+ public async Task ConnectionStateReturnsOpen()
+ {
+ var pat = await _gitlabContainer.GenerateAccessToken("root",PersonalAccessTokenScopes.api);
+ Assert.True(!string.IsNullOrEmpty(pat.Token));
+ }
+}
\ No newline at end of file
diff --git a/tests/Testcontainers.Gitlab.Tests/Testcontainers.Gitlab.Tests.csproj b/tests/Testcontainers.Gitlab.Tests/Testcontainers.Gitlab.Tests.csproj
new file mode 100644
index 000000000..d2907edff
--- /dev/null
+++ b/tests/Testcontainers.Gitlab.Tests/Testcontainers.Gitlab.Tests.csproj
@@ -0,0 +1,18 @@
+
+
+ net8.0
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Testcontainers.Gitlab.Tests/Usings.cs b/tests/Testcontainers.Gitlab.Tests/Usings.cs
new file mode 100644
index 000000000..02acb4398
--- /dev/null
+++ b/tests/Testcontainers.Gitlab.Tests/Usings.cs
@@ -0,0 +1,6 @@
+global using System.Data;
+global using System.Data.Common;
+global using System.Threading.Tasks;
+global using DotNet.Testcontainers.Commons;
+global using Microsoft.Data.SqlClient;
+global using Xunit;
\ No newline at end of file
From 2fe34db3c4c7fd99bc1847defd4770d59ae3b8d9 Mon Sep 17 00:00:00 2001
From: Peet-HD <19489992+Peet-HD@users.noreply.github.com>
Date: Tue, 2 Apr 2024 08:45:34 +0000
Subject: [PATCH 4/7] Remove logger and adjusted test
---
src/Testcontainers.Gitlab/GitlabBuilder.cs | 2 +-
src/Testcontainers.Gitlab/GitlabContainer.cs | 3 +--
.../GitlabContainerTests.cs | 18 ++++++++++++++++--
3 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/src/Testcontainers.Gitlab/GitlabBuilder.cs b/src/Testcontainers.Gitlab/GitlabBuilder.cs
index 9996ab4d0..750772552 100644
--- a/src/Testcontainers.Gitlab/GitlabBuilder.cs
+++ b/src/Testcontainers.Gitlab/GitlabBuilder.cs
@@ -44,7 +44,7 @@ private GitlabBuilder(GitlabConfiguration resourceConfiguration)
public override GitlabContainer Build()
{
Validate();
- return new GitlabContainer(DockerResourceConfiguration, TestcontainersSettings.Logger);
+ return new GitlabContainer(DockerResourceConfiguration);
}
///
diff --git a/src/Testcontainers.Gitlab/GitlabContainer.cs b/src/Testcontainers.Gitlab/GitlabContainer.cs
index ba9b02e55..2244cc195 100644
--- a/src/Testcontainers.Gitlab/GitlabContainer.cs
+++ b/src/Testcontainers.Gitlab/GitlabContainer.cs
@@ -8,9 +8,8 @@ namespace Testcontainers.Gitlab;
/// Initializes a new instance of the class.
///
/// The container configuration.
-/// The logger.
[PublicAPI]
-public sealed class GitlabContainer(GitlabConfiguration configuration, ILogger logger) : DockerContainer(configuration, logger)
+public sealed class GitlabContainer(GitlabConfiguration configuration) : DockerContainer(configuration)
{
///
/// The password for the root user
diff --git a/tests/Testcontainers.Gitlab.Tests/GitlabContainerTests.cs b/tests/Testcontainers.Gitlab.Tests/GitlabContainerTests.cs
index f1d388c62..fa2a36597 100644
--- a/tests/Testcontainers.Gitlab.Tests/GitlabContainerTests.cs
+++ b/tests/Testcontainers.Gitlab.Tests/GitlabContainerTests.cs
@@ -19,11 +19,25 @@ public Task DisposeAsync()
return _gitlabContainer.DisposeAsync().AsTask();
}
+ // [Fact]
+ // [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
+ // public async Task ConnectionStateReturnsOpen()
+ // {
+ // var pat = await _gitlabContainer.GenerateAccessToken("root",PersonalAccessTokenScopes.api);
+ // Assert.True(!string.IsNullOrEmpty(pat.Token));
+ // }
+
[Fact]
[Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
- public async Task ConnectionStateReturnsOpen()
+ public async Task GetUser()
{
var pat = await _gitlabContainer.GenerateAccessToken("root",PersonalAccessTokenScopes.api);
- Assert.True(!string.IsNullOrEmpty(pat.Token));
+
+ using var client = new HttpClient();
+ client.DefaultRequestHeaders.Add("PRIVATE-TOKEN", pat.Token);
+ var port = _gitlabContainer.GetMappedPublicPort(80);
+ var result = await client.GetAsync($"http://localhost:{port}/api/v4/user");
+
+ Assert.True(result.IsSuccessStatusCode);
}
}
\ No newline at end of file
From aaeca1f211420505d6b94101bfb9a5270b4ea939 Mon Sep 17 00:00:00 2001
From: Peet-HD <19489992+Peet-HD@users.noreply.github.com>
Date: Tue, 30 Apr 2024 00:25:42 +0200
Subject: [PATCH 5/7] set specific version for image
Set version of docker image to 16.11.1
---
src/Testcontainers.Gitlab/GitlabBuilder.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Testcontainers.Gitlab/GitlabBuilder.cs b/src/Testcontainers.Gitlab/GitlabBuilder.cs
index 750772552..46b4b6200 100644
--- a/src/Testcontainers.Gitlab/GitlabBuilder.cs
+++ b/src/Testcontainers.Gitlab/GitlabBuilder.cs
@@ -5,9 +5,9 @@ namespace Testcontainers.Gitlab;
public sealed class GitlabBuilder : ContainerBuilder
{
///
- /// This is the default image for gitlab community edition.
+ /// This is the default image for gitlab community edition in version 16.11.1 .
///
- public const string GitlabImage = "gitlab/gitlab-ce";
+ public const string GitlabImage = "gitlab/gitlab-ce:16.11.1-ce.0";
///
/// This port is used for http communication to gitlab instance.
///
From 321477f70cf5f8477b2d62e1659617f7d120453a Mon Sep 17 00:00:00 2001
From: Peet-HD <19489992+Peet-HD@users.noreply.github.com>
Date: Tue, 30 Apr 2024 00:31:13 +0200
Subject: [PATCH 6/7] Fix WaitStrategy
Fixed WaitStrategy so that all conditions are met and are not overwritten by latest condition.
---
src/Testcontainers.Gitlab/GitlabBuilder.cs | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/Testcontainers.Gitlab/GitlabBuilder.cs b/src/Testcontainers.Gitlab/GitlabBuilder.cs
index 46b4b6200..dcd411b86 100644
--- a/src/Testcontainers.Gitlab/GitlabBuilder.cs
+++ b/src/Testcontainers.Gitlab/GitlabBuilder.cs
@@ -54,11 +54,11 @@ protected override GitlabBuilder Init()
.WithImage(GitlabImage)
.WithPortBinding(GitlabHttpPort, true)
.WithPortBinding(GitlabSshPort, true)
- .WithWaitStrategy(Wait.ForUnixContainer().UntilFileExists("/etc/gitlab/initial_root_password"))
- .WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(80))
- .WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(22))
- .WithWaitStrategy(Wait.ForUnixContainer().UntilContainerIsHealthy())
- .WithWaitStrategy(Wait.ForUnixContainer().UntilHttpRequestIsSucceeded(request => request.ForPath("/users/sign_in").ForStatusCode(HttpStatusCode.OK)));
+ .WithWaitStrategy(Wait.ForUnixContainer()
+ .UntilPortIsAvailable(80)
+ .UntilPortIsAvailable(22)
+ .UntilContainerIsHealthy()
+ .UntilHttpRequestIsSucceeded(request => request.ForPath("/users/sign_in").ForStatusCode(HttpStatusCode.OK)));
}
///
From b8db1fb2a70e4590016452f56049e6ca219399f3 Mon Sep 17 00:00:00 2001
From: Peet-HD <19489992+Peet-HD@users.noreply.github.com>
Date: Wed, 1 May 2024 21:07:14 +0200
Subject: [PATCH 7/7] Made root password configurable
Add support to set the root password for gitlab
---
src/Testcontainers.Gitlab/GitlabBuilder.cs | 147 ++++++++++--------
.../GitlabConfiguration.cs | 118 ++++++++------
src/Testcontainers.Gitlab/GitlabContainer.cs | 26 +---
.../GitlabContainerTests.cs | 12 +-
4 files changed, 151 insertions(+), 152 deletions(-)
diff --git a/src/Testcontainers.Gitlab/GitlabBuilder.cs b/src/Testcontainers.Gitlab/GitlabBuilder.cs
index dcd411b86..571d75df6 100644
--- a/src/Testcontainers.Gitlab/GitlabBuilder.cs
+++ b/src/Testcontainers.Gitlab/GitlabBuilder.cs
@@ -1,78 +1,89 @@
- namespace Testcontainers.Gitlab;
-
- ///
- [PublicAPI]
- public sealed class GitlabBuilder : ContainerBuilder
- {
- ///
- /// This is the default image for gitlab community edition in version 16.11.1 .
- ///
- public const string GitlabImage = "gitlab/gitlab-ce:16.11.1-ce.0";
- ///
- /// This port is used for http communication to gitlab instance.
- ///
+namespace Testcontainers.Gitlab;
- public const ushort GitlabHttpPort = 80;
- ///
- /// This port is used for ssh communication to gitlab instance.
- ///
- public const ushort GitlabSshPort = 22;
+///
+[PublicAPI]
+public sealed class GitlabBuilder : ContainerBuilder
+{
+ ///
+ /// This is the default image for gitlab community edition in version 16.11.1 .
+ ///
+ public const string GitlabImage = "gitlab/gitlab-ce:16.11.1-ce.0";
+ ///
+ /// This port is used for http communication to gitlab instance.
+ ///
- ///
- /// Initializes a new instance of the class.
- ///
- public GitlabBuilder()
- : this(new GitlabConfiguration())
- {
- DockerResourceConfiguration = Init().DockerResourceConfiguration;
- }
+ public const ushort GitlabHttpPort = 80;
+ ///
+ /// This port is used for ssh communication to gitlab instance.
+ ///
+ public const ushort GitlabSshPort = 22;
- ///
- /// Initializes a new instance of the class.
- ///
- /// The Docker resource configuration.
- private GitlabBuilder(GitlabConfiguration resourceConfiguration)
- : base(resourceConfiguration)
- {
- DockerResourceConfiguration = resourceConfiguration;
- }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public GitlabBuilder()
+ : this(new GitlabConfiguration())
+ {
+ DockerResourceConfiguration = Init().DockerResourceConfiguration;
+ }
- ///
- protected override GitlabConfiguration DockerResourceConfiguration { get; }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Docker resource configuration.
+ private GitlabBuilder(GitlabConfiguration resourceConfiguration)
+ : base(resourceConfiguration)
+ {
+ DockerResourceConfiguration = resourceConfiguration;
+ }
- ///
- public override GitlabContainer Build()
- {
- Validate();
- return new GitlabContainer(DockerResourceConfiguration);
- }
+ ///
+ protected override GitlabConfiguration DockerResourceConfiguration { get; }
- ///
- protected override GitlabBuilder Init()
- {
- return base.Init()
- .WithImage(GitlabImage)
- .WithPortBinding(GitlabHttpPort, true)
- .WithPortBinding(GitlabSshPort, true)
- .WithWaitStrategy(Wait.ForUnixContainer()
- .UntilPortIsAvailable(80)
- .UntilPortIsAvailable(22)
- .UntilContainerIsHealthy()
- .UntilHttpRequestIsSucceeded(request => request.ForPath("/users/sign_in").ForStatusCode(HttpStatusCode.OK)));
- }
+ ///
+ public override GitlabContainer Build()
+ {
+ Validate();
+ return new GitlabContainer(DockerResourceConfiguration);
+ }
- ///
- protected override void Validate() => base.Validate();
+ ///
+ protected override GitlabBuilder Init()
+ {
+ return base.Init()
+ .WithImage(GitlabImage)
+ .WithPortBinding(GitlabHttpPort, true)
+ .WithPortBinding(GitlabSshPort, true)
+ .WithEnvironment("GITLAB_ROOT_PASSWORD", DockerResourceConfiguration.Password)
+ .WithWaitStrategy(Wait.ForUnixContainer()
+ .UntilPortIsAvailable(80)
+ .UntilPortIsAvailable(22)
+ .UntilContainerIsHealthy()
+ .UntilHttpRequestIsSucceeded(request => request.ForPath("/users/sign_in").ForStatusCode(HttpStatusCode.OK)));
+ }
- ///
- protected override GitlabBuilder Clone(IResourceConfiguration resourceConfiguration)
- => Merge(DockerResourceConfiguration, new GitlabConfiguration(resourceConfiguration));
+ ///
+ /// Sets the Gitlab password.
+ ///
+ /// The Gitlab password.
+ /// A configured instance of .
+ public GitlabBuilder WithPassword(string password)
+ {
+ return Merge(DockerResourceConfiguration, new GitlabConfiguration(password: password));
+ }
- ///
- protected override GitlabBuilder Clone(IContainerConfiguration resourceConfiguration)
- => Merge(DockerResourceConfiguration, new GitlabConfiguration(resourceConfiguration));
+ ///
+ protected override void Validate() => base.Validate();
- ///
- protected override GitlabBuilder Merge(GitlabConfiguration oldValue, GitlabConfiguration newValue)
- => new(new GitlabConfiguration(oldValue, newValue));
- }
\ No newline at end of file
+ ///
+ protected override GitlabBuilder Clone(IResourceConfiguration resourceConfiguration)
+ => Merge(DockerResourceConfiguration, new GitlabConfiguration(resourceConfiguration));
+
+ ///
+ protected override GitlabBuilder Clone(IContainerConfiguration resourceConfiguration)
+ => Merge(DockerResourceConfiguration, new GitlabConfiguration(resourceConfiguration));
+
+ ///
+ protected override GitlabBuilder Merge(GitlabConfiguration oldValue, GitlabConfiguration newValue)
+ => new(new GitlabConfiguration(oldValue, newValue));
+}
\ No newline at end of file
diff --git a/src/Testcontainers.Gitlab/GitlabConfiguration.cs b/src/Testcontainers.Gitlab/GitlabConfiguration.cs
index 64e73b523..12accd51b 100644
--- a/src/Testcontainers.Gitlab/GitlabConfiguration.cs
+++ b/src/Testcontainers.Gitlab/GitlabConfiguration.cs
@@ -1,53 +1,71 @@
namespace Testcontainers.Gitlab;
- ///
- [PublicAPI]
- public sealed class GitlabConfiguration : ContainerConfiguration
+///
+[PublicAPI]
+public sealed class GitlabConfiguration : ContainerConfiguration
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Gitlab admin password.
+ public GitlabConfiguration(string password)
{
- ///
- /// Initializes a new instance of the class.
- ///
- public GitlabConfiguration()
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The Docker resource configuration.
- public GitlabConfiguration(IResourceConfiguration resourceConfiguration)
- : base(resourceConfiguration)
- {
- // Passes the configuration upwards to the base implementations to create an updated immutable copy.
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The Docker resource configuration.
- public GitlabConfiguration(IContainerConfiguration resourceConfiguration)
- : base(resourceConfiguration)
- {
- // Passes the configuration upwards to the base implementations to create an updated immutable copy.
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The Docker resource configuration.
- public GitlabConfiguration(GitlabConfiguration resourceConfiguration)
- : this(new GitlabConfiguration(), resourceConfiguration)
- {
- // Passes the configuration upwards to the base implementations to create an updated immutable copy.
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The old Docker resource configuration.
- /// The new Docker resource configuration.
- public GitlabConfiguration(GitlabConfiguration oldValue, GitlabConfiguration newValue)
- : base(oldValue, newValue)
- {
- }
- }
\ No newline at end of file
+ _password = password;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public GitlabConfiguration()
+ {
+ _password = Guid.NewGuid().ToString();
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Docker resource configuration.
+ public GitlabConfiguration(IResourceConfiguration resourceConfiguration)
+ : base(resourceConfiguration)
+ {
+ // Passes the configuration upwards to the base implementations to create an updated immutable copy.
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Docker resource configuration.
+ public GitlabConfiguration(IContainerConfiguration resourceConfiguration)
+ : base(resourceConfiguration)
+ {
+ // Passes the configuration upwards to the base implementations to create an updated immutable copy.
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Docker resource configuration.
+ public GitlabConfiguration(GitlabConfiguration resourceConfiguration)
+ : this(new GitlabConfiguration(), resourceConfiguration)
+ {
+ // Passes the configuration upwards to the base implementations to create an updated immutable copy.
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The old Docker resource configuration.
+ /// The new Docker resource configuration.
+ public GitlabConfiguration(GitlabConfiguration oldValue, GitlabConfiguration newValue)
+ : base(oldValue, newValue)
+ {
+ _password = BuildConfiguration.Combine(oldValue.Password, newValue.Password);
+ }
+
+ ///
+ /// Gets the Gitlab admin password.
+ ///
+ public string Password => _password;
+
+ private readonly string _password;
+}
\ No newline at end of file
diff --git a/src/Testcontainers.Gitlab/GitlabContainer.cs b/src/Testcontainers.Gitlab/GitlabContainer.cs
index 2244cc195..712e0f664 100644
--- a/src/Testcontainers.Gitlab/GitlabContainer.cs
+++ b/src/Testcontainers.Gitlab/GitlabContainer.cs
@@ -12,15 +12,10 @@ namespace Testcontainers.Gitlab;
public sealed class GitlabContainer(GitlabConfiguration configuration) : DockerContainer(configuration)
{
///
- /// The password for the root user
+ /// Gets the root password.
///
- public string RootPassword { get; private set; }
+ public string Password => configuration.Password;
- public override async Task StartAsync(CancellationToken ct = default)
- {
- await base.StartAsync(ct);
- RootPassword = await GetInitialRootPassword();
- }
///
/// Generate a personal access token.
@@ -45,7 +40,7 @@ public async Task GenerateAccessToken(PersonalAccessToken p
ExecResult tokenResult = await ExecAsync(tokenCommand);
- string token = "";
+ string token;
if (tokenResult.ExitCode == 0)
{
var match = GitlabRegex.GitlabPersonalAccessToken.Match(tokenResult.Stdout);
@@ -75,19 +70,4 @@ public async Task GenerateAccessToken(string user, Personal
Scope = scope,
ExpirationInDays = expirationInDays
});
-
-
- ///
- /// This method returns the initial root password for the gitlab root user.
- ///
- /// Returns the initial root password generated by gitlab.
- private async Task GetInitialRootPassword()
- {
- var byteArray = await ReadFileAsync("/etc/gitlab/initial_root_password");
-
- string fileContent = Encoding.UTF8.GetString(byteArray);
- var match = GitlabRegex.GitlabRootPassword.Match(fileContent);
- string[] splits = match.Value.Split(' ');
- return splits[1];
- }
}
\ No newline at end of file
diff --git a/tests/Testcontainers.Gitlab.Tests/GitlabContainerTests.cs b/tests/Testcontainers.Gitlab.Tests/GitlabContainerTests.cs
index fa2a36597..da19a02b6 100644
--- a/tests/Testcontainers.Gitlab.Tests/GitlabContainerTests.cs
+++ b/tests/Testcontainers.Gitlab.Tests/GitlabContainerTests.cs
@@ -1,7 +1,5 @@
using Testcontainers.Gitlab.Models;
-using Testcontainers.Gitlab.RegexPatterns;
using System.Net.Http;
-using System;
namespace Testcontainers.Gitlab;
@@ -19,19 +17,11 @@ public Task DisposeAsync()
return _gitlabContainer.DisposeAsync().AsTask();
}
- // [Fact]
- // [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
- // public async Task ConnectionStateReturnsOpen()
- // {
- // var pat = await _gitlabContainer.GenerateAccessToken("root",PersonalAccessTokenScopes.api);
- // Assert.True(!string.IsNullOrEmpty(pat.Token));
- // }
-
[Fact]
[Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
public async Task GetUser()
{
- var pat = await _gitlabContainer.GenerateAccessToken("root",PersonalAccessTokenScopes.api);
+ var pat = await _gitlabContainer.GenerateAccessToken("root", PersonalAccessTokenScopes.api);
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("PRIVATE-TOKEN", pat.Token);