-
-
Notifications
You must be signed in to change notification settings - Fork 290
/
MsSqlBuilder.cs
152 lines (130 loc) · 5.3 KB
/
MsSqlBuilder.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
namespace Testcontainers.MsSql;
/// <inheritdoc cref="ContainerBuilder{TBuilderEntity, TContainerEntity, TConfigurationEntity}" />
[PublicAPI]
public sealed class MsSqlBuilder : ContainerBuilder<MsSqlBuilder, MsSqlContainer, MsSqlConfiguration>
{
public const string MsSqlImage = "mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04";
public const ushort MsSqlPort = 1433;
public const string DefaultDatabase = "master";
public const string DefaultUsername = "sa";
public const string DefaultPassword = "yourStrong(!)Password";
/// <summary>
/// Initializes a new instance of the <see cref="MsSqlBuilder" /> class.
/// </summary>
public MsSqlBuilder()
: this(new MsSqlConfiguration())
{
DockerResourceConfiguration = Init().DockerResourceConfiguration;
}
/// <summary>
/// Initializes a new instance of the <see cref="MsSqlBuilder" /> class.
/// </summary>
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
private MsSqlBuilder(MsSqlConfiguration resourceConfiguration)
: base(resourceConfiguration)
{
DockerResourceConfiguration = resourceConfiguration;
}
/// <inheritdoc />
protected override MsSqlConfiguration DockerResourceConfiguration { get; }
/// <summary>
/// Sets the MsSql password.
/// </summary>
/// <param name="password">The MsSql password.</param>
/// <returns>A configured instance of <see cref="MsSqlBuilder" />.</returns>
public MsSqlBuilder WithPassword(string password)
{
return Merge(DockerResourceConfiguration, new MsSqlConfiguration(password: password))
.WithEnvironment("MSSQL_SA_PASSWORD", password)
.WithEnvironment("SQLCMDPASSWORD", password);
}
/// <inheritdoc />
public override MsSqlContainer Build()
{
Validate();
return new MsSqlContainer(DockerResourceConfiguration);
}
/// <inheritdoc />
protected override MsSqlBuilder Init()
{
return base.Init()
.WithImage(MsSqlImage)
.WithPortBinding(MsSqlPort, true)
.WithEnvironment("ACCEPT_EULA", "Y")
.WithDatabase(DefaultDatabase)
.WithUsername(DefaultUsername)
.WithPassword(DefaultPassword)
.WithWaitStrategy(Wait.ForUnixContainer().AddCustomWaitStrategy(new WaitUntil()));
}
/// <inheritdoc />
protected override void Validate()
{
base.Validate();
_ = Guard.Argument(DockerResourceConfiguration.Password, nameof(DockerResourceConfiguration.Password))
.NotNull()
.NotEmpty();
}
/// <inheritdoc />
protected override MsSqlBuilder Clone(IResourceConfiguration<CreateContainerParameters> resourceConfiguration)
{
return Merge(DockerResourceConfiguration, new MsSqlConfiguration(resourceConfiguration));
}
/// <inheritdoc />
protected override MsSqlBuilder Clone(IContainerConfiguration resourceConfiguration)
{
return Merge(DockerResourceConfiguration, new MsSqlConfiguration(resourceConfiguration));
}
/// <inheritdoc />
protected override MsSqlBuilder Merge(MsSqlConfiguration oldValue, MsSqlConfiguration newValue)
{
return new MsSqlBuilder(new MsSqlConfiguration(oldValue, newValue));
}
/// <summary>
/// Sets the MsSql database.
/// </summary>
/// <remarks>
/// The Docker image does not allow to configure the database.
/// </remarks>
/// <param name="database">The MsSql database.</param>
/// <returns>A configured instance of <see cref="MsSqlBuilder" />.</returns>
private MsSqlBuilder WithDatabase(string database)
{
return Merge(DockerResourceConfiguration, new MsSqlConfiguration(database: database))
.WithEnvironment("SQLCMDDBNAME", database);
}
/// <summary>
/// Sets the MsSql username.
/// </summary>
/// <remarks>
/// The Docker image does not allow to configure the username.
/// </remarks>
/// <param name="username">The MsSql username.</param>
/// <returns>A configured instance of <see cref="MsSqlBuilder" />.</returns>
private MsSqlBuilder WithUsername(string username)
{
return Merge(DockerResourceConfiguration, new MsSqlConfiguration(username: username))
.WithEnvironment("SQLCMDUSER", username);
}
/// <inheritdoc cref="IWaitUntil" />
/// <remarks>
/// Uses the <c>sqlcmd</c> utility scripting variables to detect readiness of the MsSql container:
/// https://learn.microsoft.com/en-us/sql/tools/sqlcmd/sqlcmd-utility?view=sql-server-linux-ver15#sqlcmd-scripting-variables.
/// </remarks>
private sealed class WaitUntil : IWaitUntil
{
/// <inheritdoc />
public Task<bool> UntilAsync(IContainer container)
{
return UntilAsync(container as MsSqlContainer);
}
/// <inheritdoc cref="IWaitUntil.UntilAsync" />
private static async Task<bool> UntilAsync(MsSqlContainer container)
{
var sqlCmdFilePath = await container.GetSqlCmdFilePathAsync()
.ConfigureAwait(false);
var execResult = await container.ExecAsync(new[] { sqlCmdFilePath, "-C", "-Q", "SELECT 1;" })
.ConfigureAwait(false);
return 0L.Equals(execResult.ExitCode);
}
}
}