Skip to content

Commit 946f4f5

Browse files
authored
Add DbGate support for MySql (#695)
1 parent deab95f commit 946f4f5

File tree

9 files changed

+390
-6
lines changed

9 files changed

+390
-6
lines changed

examples/dbgate/CommunityToolkit.Aspire.Hosting.DbGate.AppHost/CommunityToolkit.Aspire.Hosting.DbGate.AppHost.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
<ProjectReference Include="..\..\..\src\CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions\CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions.csproj" IsAspireProjectResource="false" />
1919
<ProjectReference Include="..\..\..\src\CommunityToolkit.Aspire.Hosting.Redis.Extensions\CommunityToolkit.Aspire.Hosting.Redis.Extensions.csproj" IsAspireProjectResource="false" />
2020
<ProjectReference Include="..\..\..\src\CommunityToolkit.Aspire.Hosting.SqlServer.Extensions\CommunityToolkit.Aspire.Hosting.SqlServer.Extensions.csproj" IsAspireProjectResource="false" />
21+
<ProjectReference Include="..\..\..\src\CommunityToolkit.Aspire.Hosting.MySql.Extensions\CommunityToolkit.Aspire.Hosting.MySql.Extensions.csproj" IsAspireProjectResource="false" />
2122
</ItemGroup>
2223

2324

examples/dbgate/CommunityToolkit.Aspire.Hosting.DbGate.AppHost/Program.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,14 @@
3232
sqlserver2.AddDatabase("db12");
3333

3434

35+
var mysql1 = builder.AddMySql("mysql1")
36+
.WithDbGate(c => c.WithHostPort(8068));
37+
mysql1.AddDatabase("db13");
38+
mysql1.AddDatabase("db14");
39+
40+
var mysql2 = builder.AddMySql("mysql2")
41+
.WithDbGate();
42+
mysql2.AddDatabase("db15");
43+
mysql2.AddDatabase("db16");
44+
3545
builder.Build().Run();

examples/mysql-ext/CommunityToolkit.Aspire.Hosting.MySql.Extensions.AppHost/Program.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
var builder = DistributedApplication.CreateBuilder(args);
22

33
var mysql1 = builder.AddMySql("mysql1")
4-
.WithAdminer(c => c.WithHostPort(8989));
4+
.WithAdminer(c => c.WithHostPort(8989))
5+
.WithDbGate(c => c.WithHostPort(9999));
56
mysql1.AddDatabase("db1");
67
mysql1.AddDatabase("db2");
78

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11

22
internal static class DbGateContainerImageTags
33
{
4-
/// <summary>docker.io</summary>
4+
/// <remarks>docker.io</remarks>
55
public const string Registry = "docker.io";
6-
/// <summary>dbgate/dbgate</summary>
6+
/// <remarks>dbgate/dbgate</remarks>
77
public const string Image = "dbgate/dbgate";
8-
/// <summary>6.1.4</summary>
8+
/// <remarks>6.1.4</remarks>
99
public const string Tag = "6.1.4";
1010
}
1111

src/CommunityToolkit.Aspire.Hosting.MySql.Extensions/CommunityToolkit.Aspire.Hosting.MySql.Extensions.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
<ItemGroup>
1414
<ProjectReference Include="..\CommunityToolkit.Aspire.Hosting.Adminer\CommunityToolkit.Aspire.Hosting.Adminer.csproj" />
15+
<ProjectReference Include="..\CommunityToolkit.Aspire.Hosting.DbGate\CommunityToolkit.Aspire.Hosting.DbGate.csproj" />
1516
</ItemGroup>
1617

1718
<ItemGroup>

src/CommunityToolkit.Aspire.Hosting.MySql.Extensions/MySqlBuilderExtensions.cs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,91 @@ public static IResourceBuilder<MySqlServerResource> WithAdminer(this IResourceBu
5050
return builder;
5151
}
5252

53+
/// <summary>
54+
/// Adds an administration and development platform for MySql to the application model using DbGate.
55+
/// </summary>
56+
/// <remarks>
57+
/// This version of the package defaults to the <inheritdoc cref="DbGateContainerImageTags.Tag"/> tag of the <inheritdoc cref="DbGateContainerImageTags.Image"/> container image.
58+
/// <param name="builder">The MySql server resource builder.</param>
59+
/// <param name="configureContainer">Configuration callback for DbGate container resource.</param>
60+
/// <param name="containerName">The name of the container (Optional).</param>
61+
/// <example>
62+
/// Use in application host with a MySql resource
63+
/// <code lang="csharp">
64+
/// var builder = DistributedApplication.CreateBuilder(args);
65+
///
66+
/// var mysql = builder.AddMySql("mysql")
67+
/// .WithDbGate();
68+
/// var db = mysql.AddDatabase("db");
69+
///
70+
/// var api = builder.AddProject&lt;Projects.Api&gt;("api")
71+
/// .WithReference(db);
72+
///
73+
/// builder.Build().Run();
74+
/// </code>
75+
/// </example>
76+
/// </remarks>
77+
/// <returns>A reference to the <see cref="IResourceBuilder{T}"/>.</returns>
78+
public static IResourceBuilder<MySqlServerResource> WithDbGate(this IResourceBuilder<MySqlServerResource> builder, Action<IResourceBuilder<DbGateContainerResource>>? configureContainer = null, string? containerName = null)
79+
{
80+
ArgumentNullException.ThrowIfNull(builder);
81+
82+
containerName ??= $"{builder.Resource.Name}-dbgate";
83+
84+
var dbGateBuilder = DbGateBuilderExtensions.AddDbGate(builder.ApplicationBuilder, containerName);
85+
86+
dbGateBuilder
87+
.WithEnvironment(context => ConfigureDbGateContainer(context, builder.ApplicationBuilder));
88+
89+
configureContainer?.Invoke(dbGateBuilder);
90+
91+
return builder;
92+
}
93+
94+
private static void ConfigureDbGateContainer(EnvironmentCallbackContext context, IDistributedApplicationBuilder applicationBuilder)
95+
{
96+
var mysqlInstances = applicationBuilder.Resources.OfType<MySqlServerResource>();
97+
98+
var counter = 1;
99+
100+
// Multiple WithDbGate calls will be ignored
101+
if (context.EnvironmentVariables.ContainsKey($"LABEL_mysql{counter}"))
102+
{
103+
return;
104+
}
105+
106+
foreach (var mySqlServerResource in mysqlInstances)
107+
{
108+
// DbGate assumes MySql is being accessed over a default Aspire container network and hardcodes the resource address
109+
context.EnvironmentVariables.Add($"LABEL_mysql{counter}", mySqlServerResource.Name);
110+
context.EnvironmentVariables.Add($"SERVER_mysql{counter}", mySqlServerResource.Name);
111+
context.EnvironmentVariables.Add($"USER_mysql{counter}", "root");
112+
context.EnvironmentVariables.Add($"PASSWORD_mysql{counter}", mySqlServerResource.PasswordParameter.Value);
113+
context.EnvironmentVariables.Add($"PORT_mysql{counter}", mySqlServerResource.PrimaryEndpoint.TargetPort!.ToString()!);
114+
context.EnvironmentVariables.Add($"ENGINE_mysql{counter}", "mysql@dbgate-plugin-mysql");
115+
116+
counter++;
117+
}
118+
119+
var instancesCount = mysqlInstances.Count();
120+
if (instancesCount > 0)
121+
{
122+
var strBuilder = new StringBuilder();
123+
strBuilder.AppendJoin(',', Enumerable.Range(1, instancesCount).Select(i => $"mysql{i}"));
124+
var connections = strBuilder.ToString();
125+
126+
string CONNECTIONS = context.EnvironmentVariables.GetValueOrDefault("CONNECTIONS")?.ToString() ?? string.Empty;
127+
if (string.IsNullOrEmpty(CONNECTIONS))
128+
{
129+
context.EnvironmentVariables["CONNECTIONS"] = connections;
130+
}
131+
else
132+
{
133+
context.EnvironmentVariables["CONNECTIONS"] += $",{connections}";
134+
}
135+
}
136+
}
137+
53138
internal static void ConfigureAdminerContainer(EnvironmentCallbackContext context, IDistributedApplicationBuilder applicationBuilder)
54139
{
55140
var mysqlInstances = applicationBuilder.Resources.OfType<MySqlServerResource>();

src/CommunityToolkit.Aspire.Hosting.MySql.Extensions/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
This integration contains extensions for the [MySql hosting package](https://nuget.org/packages/Aspire.Hosting.MySql) for .NET Aspire.
44

5-
The integration provides support for running [Adminer](https://github.com/vrana/adminer) to interact with the MySql database.
5+
The integration provides support for running [Adminer](https://github.com/vrana/adminer) and [DbGate](https://github.com/dbgate/dbgate) to interact with the MySql database.
66

77
## Getting Started
88

@@ -20,6 +20,7 @@ Then, in the _Program.cs_ file of `AppHost`, define an MySql resource, then call
2020

2121
```csharp
2222
var mysql = builder.AddMySql("mysql")
23+
.WithDbGate()
2324
.WithAdminer();
2425
```
2526

tests/CommunityToolkit.Aspire.Hosting.DbGate.Tests/AddDbGateTests.cs

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,16 @@ public async Task WithDbGateShouldAddAnnotationsForMultipleDatabaseTypes()
221221

222222
var sqlserverResource2 = sqlserverResourceBuilder2.Resource;
223223

224+
var mysqlResourceBuilder1 = builder.AddMySql("mysql1")
225+
.WithDbGate();
226+
227+
var mysqlResource1 = mysqlResourceBuilder1.Resource;
228+
229+
var mysqlResourceBuilder2 =builder.AddMySql("mysql2")
230+
.WithDbGate();
231+
232+
var mysqlResource2 = mysqlResourceBuilder2.Resource;
233+
224234
using var app = builder.Build();
225235

226236
var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();
@@ -268,7 +278,7 @@ public async Task WithDbGateShouldAddAnnotationsForMultipleDatabaseTypes()
268278
item =>
269279
{
270280
Assert.Equal("CONNECTIONS", item.Key);
271-
Assert.Equal("mongodb1,mongodb2,postgres1,postgres2,redis1,redis2,sqlserver1,sqlserver2", item.Value);
281+
Assert.Equal("mongodb1,mongodb2,postgres1,postgres2,redis1,redis2,sqlserver1,sqlserver2,mysql1,mysql2", item.Value);
272282
},
273283
item =>
274284
{
@@ -423,6 +433,66 @@ public async Task WithDbGateShouldAddAnnotationsForMultipleDatabaseTypes()
423433
{
424434
Assert.Equal("ENGINE_sqlserver2", item.Key);
425435
Assert.Equal("mssql@dbgate-plugin-mssql", item.Value);
436+
},
437+
item =>
438+
{
439+
Assert.Equal("LABEL_mysql1", item.Key);
440+
Assert.Equal(mysqlResource1.Name, item.Value);
441+
},
442+
item =>
443+
{
444+
Assert.Equal("SERVER_mysql1", item.Key);
445+
Assert.Equal(mysqlResource1.Name, item.Value);
446+
},
447+
item =>
448+
{
449+
Assert.Equal("USER_mysql1", item.Key);
450+
Assert.Equal("root", item.Value);
451+
},
452+
item =>
453+
{
454+
Assert.Equal("PASSWORD_mysql1", item.Key);
455+
Assert.Equal(mysqlResource1.PasswordParameter.Value, item.Value);
456+
},
457+
item =>
458+
{
459+
Assert.Equal("PORT_mysql1", item.Key);
460+
Assert.Equal(mysqlResource1.PrimaryEndpoint.TargetPort.ToString(), item.Value);
461+
},
462+
item =>
463+
{
464+
Assert.Equal("ENGINE_mysql1", item.Key);
465+
Assert.Equal("mysql@dbgate-plugin-mysql", item.Value);
466+
},
467+
item =>
468+
{
469+
Assert.Equal("LABEL_mysql2", item.Key);
470+
Assert.Equal(mysqlResource2.Name, item.Value);
471+
},
472+
item =>
473+
{
474+
Assert.Equal("SERVER_mysql2", item.Key);
475+
Assert.Equal(mysqlResource2.Name, item.Value);
476+
},
477+
item =>
478+
{
479+
Assert.Equal("USER_mysql2", item.Key);
480+
Assert.Equal("root", item.Value);
481+
},
482+
item =>
483+
{
484+
Assert.Equal("PASSWORD_mysql2", item.Key);
485+
Assert.Equal(mysqlResource2.PasswordParameter.Value, item.Value);
486+
},
487+
item =>
488+
{
489+
Assert.Equal("PORT_mysql2", item.Key);
490+
Assert.Equal(mysqlResource2.PrimaryEndpoint.TargetPort.ToString(), item.Value);
491+
},
492+
item =>
493+
{
494+
Assert.Equal("ENGINE_mysql2", item.Key);
495+
Assert.Equal("mysql@dbgate-plugin-mysql", item.Value);
426496
});
427497
}
428498

@@ -455,6 +525,12 @@ public void WithDbGateShouldShouldAddOneDbGateResourceForMultipleDatabaseTypes()
455525
builder.AddSqlServer("sqlserver2")
456526
.WithDbGate();
457527

528+
builder.AddMySql("mysql1")
529+
.WithDbGate();
530+
531+
builder.AddMySql("mysql2")
532+
.WithDbGate();
533+
458534
using var app = builder.Build();
459535

460536
var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();

0 commit comments

Comments
 (0)