Skip to content

Commit bfbe2d2

Browse files
authored
Add Adminer support for SqlServer (#679)
* Add Adminer support for SqlServer * Add tests
1 parent 085d6bc commit bfbe2d2

File tree

9 files changed

+301
-4
lines changed

9 files changed

+301
-4
lines changed

examples/adminer/CommunityToolkit.Aspire.Hosting.Adminer.AppHost/CommunityToolkit.Aspire.Hosting.Adminer.AppHost.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<ItemGroup>
1616
<ProjectReference Include="..\..\..\src\CommunityToolkit.Aspire.Hosting.Adminer\CommunityToolkit.Aspire.Hosting.Adminer.csproj" IsAspireProjectResource="false" />
1717
<ProjectReference Include="..\..\..\src\CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions\CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions.csproj" IsAspireProjectResource="false" />
18+
<ProjectReference Include="..\..\..\src\CommunityToolkit.Aspire.Hosting.SqlServer.Extensions\CommunityToolkit.Aspire.Hosting.SqlServer.Extensions.csproj" IsAspireProjectResource="false" />
1819
</ItemGroup>
1920

2021
</Project>

examples/adminer/CommunityToolkit.Aspire.Hosting.Adminer.AppHost/Program.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,14 @@
1010
postgres2.AddDatabase("db3");
1111
postgres2.AddDatabase("db4");
1212

13+
var sqlserver1 = builder.AddSqlServer("sqlserver1")
14+
.WithAdminer();
15+
sqlserver1.AddDatabase("db5");
16+
sqlserver1.AddDatabase("db6");
17+
18+
var sqlserver2 = builder.AddSqlServer("sqlserver2")
19+
.WithAdminer();
20+
sqlserver2.AddDatabase("db7");
21+
sqlserver2.AddDatabase("db8");
22+
1323
builder.Build().Run();

examples/sqlserver-ext/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions.AppHost/Program.cs

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

33
var sqlserver1 = builder.AddSqlServer("sqlserver1")
4-
.WithDbGate(c => c.WithHostPort(8068));
4+
.WithDbGate(c => c.WithHostPort(8068))
5+
.WithAdminer(c => c.WithHostPort(8069));
56
sqlserver1.AddDatabase("db1");
67
sqlserver1.AddDatabase("db2");
78

89
var sqlserver2 = builder.AddSqlServer("sqlserver2")
9-
.WithDbGate();
10+
.WithDbGate()
11+
.WithAdminer();
1012
sqlserver2.AddDatabase("db3");
1113
sqlserver2.AddDatabase("db4");
1214

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,14 @@
1111
</ItemGroup>
1212

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

18+
<ItemGroup>
19+
<Compile Include="$(SharedDir)\Adminer\AdminerLoginServer.cs" Link="AdminerLoginServer.cs" />
20+
</ItemGroup>
21+
1722
<!-- Workaround for https://github.com/dotnet/aspire/issues/7779 -->
1823
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
1924
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />

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

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

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

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

77
## Getting Started
88

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

2121
```csharp
2222
var sqlserver = builder.AddSqlServer("sqlserver")
23-
.WithDbGate();
23+
.WithDbGate()
24+
.WithAdminer();
2425
```
2526

2627
## Additional Information

src/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions/SqlServerBuilderExtensions.cs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Aspire.Hosting.ApplicationModel;
22
using System.Text;
3+
using System.Text.Json;
34

45
namespace Aspire.Hosting;
56

@@ -49,6 +50,46 @@ public static IResourceBuilder<SqlServerServerResource> WithDbGate(this IResourc
4950
return builder;
5051
}
5152

53+
/// <summary>
54+
/// Adds an administration and development platform for SqlServer to the application model using Adminer.
55+
/// </summary>
56+
/// <remarks>
57+
/// This version of the package defaults to the <inheritdoc cref="AdminerContainerImageTags.Tag"/> tag of the <inheritdoc cref="AdminerContainerImageTags.Image"/> container image.
58+
/// <param name="builder">The SqlServer server resource builder.</param>
59+
/// <param name="configureContainer">Configuration callback for Adminer container resource.</param>
60+
/// <param name="containerName">The name of the container (Optional).</param>
61+
/// <example>
62+
/// Use in application host with a SqlServer resource
63+
/// <code lang="csharp">
64+
/// var builder = DistributedApplication.CreateBuilder(args);
65+
///
66+
/// var sqlserver = builder.AddSqlServer("sqlserver")
67+
/// .WithAdminer();
68+
/// var db = sqlserver.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<SqlServerServerResource> WithAdminer(this IResourceBuilder<SqlServerServerResource> builder, Action<IResourceBuilder<AdminerContainerResource>>? configureContainer = null, string? containerName = null)
79+
{
80+
ArgumentNullException.ThrowIfNull(builder);
81+
82+
containerName ??= $"{builder.Resource.Name}-adminer";
83+
var adminerBuilder = AdminerBuilderExtensions.AddAdminer(builder.ApplicationBuilder, containerName);
84+
85+
adminerBuilder
86+
.WithEnvironment(context => ConfigureAdminerContainer(context, builder.ApplicationBuilder));
87+
88+
configureContainer?.Invoke(adminerBuilder);
89+
90+
return builder;
91+
}
92+
5293
private static void ConfigureDbGateContainer(EnvironmentCallbackContext context, IDistributedApplicationBuilder applicationBuilder)
5394
{
5495
var sqlServerInstances = applicationBuilder.Resources.OfType<SqlServerServerResource>();
@@ -93,4 +134,45 @@ private static void ConfigureDbGateContainer(EnvironmentCallbackContext context,
93134
}
94135
}
95136
}
137+
138+
private static void ConfigureAdminerContainer(EnvironmentCallbackContext context, IDistributedApplicationBuilder applicationBuilder)
139+
{
140+
var sqlServerInstances = applicationBuilder.Resources.OfType<SqlServerServerResource>();
141+
142+
string ADMINER_SERVERS = context.EnvironmentVariables.GetValueOrDefault("ADMINER_SERVERS")?.ToString() ?? string.Empty;
143+
144+
var new_servers = sqlServerInstances.ToDictionary(
145+
sqlServerServerResource => sqlServerServerResource.Name,
146+
sqlServerServerResource =>
147+
{
148+
return new AdminerLoginServer
149+
{
150+
Server = sqlServerServerResource.Name,
151+
UserName = "sa",
152+
Password = sqlServerServerResource.PasswordParameter.Value,
153+
Driver = "mssql"
154+
};
155+
});
156+
157+
if (string.IsNullOrEmpty(ADMINER_SERVERS))
158+
{
159+
string servers_json = JsonSerializer.Serialize(new_servers);
160+
context.EnvironmentVariables["ADMINER_SERVERS"] = servers_json;
161+
}
162+
else
163+
{
164+
var servers = JsonSerializer.Deserialize<Dictionary<string, AdminerLoginServer>>(ADMINER_SERVERS) ?? throw new InvalidOperationException("The servers should not be null. This should never happen.");
165+
foreach (var server in new_servers)
166+
{
167+
if (!servers.ContainsKey(server.Key))
168+
{
169+
servers!.Add(server.Key, server.Value);
170+
}
171+
}
172+
string servers_json = JsonSerializer.Serialize(servers);
173+
context.EnvironmentVariables["ADMINER_SERVERS"] = servers_json;
174+
}
175+
176+
}
177+
96178
}

tests/CommunityToolkit.Aspire.Hosting.Adminer.Tests/AddAdminerTests.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,16 @@ public async Task WithAdminerShouldAddAnnotationsForMultipleDatabaseTypes()
146146

147147
var postgresResource2 = postgresResourceBuilder2.Resource;
148148

149+
var sqlserverResourceBuilder1 = builder.AddSqlServer("sqlserver1")
150+
.WithAdminer();
151+
152+
var sqlserverResource1 = sqlserverResourceBuilder1.Resource;
153+
154+
var sqlserverResourceBuilder2 = builder.AddSqlServer("sqlserver2")
155+
.WithAdminer();
156+
157+
var sqlserverResource2 = sqlserverResourceBuilder2.Resource;
158+
149159
using var app = builder.Build();
150160

151161
var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();
@@ -181,6 +191,26 @@ public async Task WithAdminerShouldAddAnnotationsForMultipleDatabaseTypes()
181191
Password = postgresResource2.PasswordParameter.Value,
182192
UserName = postgresResource2.UserNameParameter?.Value ?? "postgres"
183193
}
194+
},
195+
{
196+
"sqlserver1",
197+
new AdminerLoginServer
198+
{
199+
Driver = "mssql",
200+
Server = sqlserverResource1.Name,
201+
Password = sqlserverResource1.PasswordParameter.Value,
202+
UserName = "sa"
203+
}
204+
},
205+
{
206+
"sqlserver2",
207+
new AdminerLoginServer
208+
{
209+
Driver = "mssql",
210+
Server = sqlserverResource2.Name,
211+
Password = sqlserverResource2.PasswordParameter.Value,
212+
UserName = "sa"
213+
}
184214
}
185215
};
186216

@@ -201,6 +231,12 @@ public void WithAdminerShouldShouldAddOneAdminerResourceForMultipleDatabaseTypes
201231
builder.AddPostgres("postgres2")
202232
.WithAdminer();
203233

234+
builder.AddSqlServer("sqlserver1")
235+
.WithAdminer();
236+
237+
builder.AddSqlServer("sqlserver2")
238+
.WithAdminer();
239+
204240
using var app = builder.Build();
205241

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

tests/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions.Tests/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions.Tests.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,7 @@
44
<ProjectReference Include="..\..\src\CommunityToolkit.Aspire.Hosting.SqlServer.Extensions\CommunityToolkit.Aspire.Hosting.SqlServer.Extensions.csproj" />
55
<ProjectReference Include="..\CommunityToolkit.Aspire.Testing\CommunityToolkit.Aspire.Testing.csproj" />
66
</ItemGroup>
7+
<ItemGroup>
8+
<Compile Include="$(SharedDir)\Adminer\AdminerLoginServer.cs" Link="AdminerLoginServer.cs" />
9+
</ItemGroup>
710
</Project>

0 commit comments

Comments
 (0)