diff --git a/src/Aspire.Hosting/MySql/IMySqlParentResource.cs b/src/Aspire.Hosting/MySql/IMySqlParentResource.cs
deleted file mode 100644
index eb72e185ec..0000000000
--- a/src/Aspire.Hosting/MySql/IMySqlParentResource.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace Aspire.Hosting.ApplicationModel;
-
-///
-/// Represents a MySQL parent resource (container or server) that produces a connection string.
-///
-public interface IMySqlParentResource : IResourceWithConnectionString, IResourceWithEnvironment
-{
-}
diff --git a/src/Aspire.Hosting/MySql/MySqlBuilderExtensions.cs b/src/Aspire.Hosting/MySql/MySqlBuilderExtensions.cs
index f99fa21c80..ba05fdcb6a 100644
--- a/src/Aspire.Hosting/MySql/MySqlBuilderExtensions.cs
+++ b/src/Aspire.Hosting/MySql/MySqlBuilderExtensions.cs
@@ -17,58 +17,41 @@ public static class MySqlBuilderExtensions
private const string PasswordEnvVarName = "MYSQL_ROOT_PASSWORD";
///
- /// Adds a MySQL container to the application model. The default image is "mysql" and the tag is "latest".
+ /// Adds a MySQL server resource to the application model. For local development a container is used.
///
/// The .
/// The name of the resource. This name will be used as the connection string name when referenced in a dependency.
/// The host port for MySQL.
/// The password for the MySQL root user. Defaults to a random password.
/// A reference to the .
- public static IResourceBuilder AddMySqlContainer(this IDistributedApplicationBuilder builder, string name, int? port = null, string? password = null)
+ public static IResourceBuilder AddMySql(this IDistributedApplicationBuilder builder, string name, int? port = null, string? password = null)
{
- password ??= Guid.NewGuid().ToString("N");
- var mySqlContainer = new MySqlContainerResource(name, password);
- return builder.AddResource(mySqlContainer)
- .WithManifestPublishingCallback(context => WriteMySqlContainerResourceToManifest(context, mySqlContainer))
+ password = password ?? Guid.NewGuid().ToString("N");
+ var resource = new MySqlServerResource(name, password);
+ return builder.AddResource(resource)
+ .WithManifestPublishingCallback(WriteMySqlContainerToManifest)
.WithAnnotation(new EndpointAnnotation(ProtocolType.Tcp, port: port, containerPort: 3306)) // Internal port is always 3306.
.WithAnnotation(new ContainerImageAnnotation { Image = "mysql", Tag = "latest" })
.WithEnvironment(context =>
{
if (context.PublisherName == "manifest")
{
- context.EnvironmentVariables.Add(PasswordEnvVarName, $"{{{mySqlContainer.Name}.inputs.password}}");
+ context.EnvironmentVariables.Add(PasswordEnvVarName, $"{{{resource.Name}.inputs.password}}");
}
else
{
- context.EnvironmentVariables.Add(PasswordEnvVarName, mySqlContainer.Password);
+ context.EnvironmentVariables.Add(PasswordEnvVarName, resource.Password);
}
});
}
- ///
- /// Adds a MySQL server resource to the application model. For local development a container is used.
- ///
- /// The .
- /// The name of the resource. This name will be used as the connection string name when referenced in a dependency.
- /// A reference to the .
- public static IResourceBuilder AddMySql(this IDistributedApplicationBuilder builder, string name)
- {
- var password = Guid.NewGuid().ToString("N");
- var mySqlContainer = new MySqlServerResource(name, password);
- return builder.AddResource(mySqlContainer)
- .WithManifestPublishingCallback(WriteMySqlContainerToManifest)
- .WithAnnotation(new EndpointAnnotation(ProtocolType.Tcp, containerPort: 3306)) // Internal port is always 3306.
- .WithAnnotation(new ContainerImageAnnotation { Image = "mysql", Tag = "latest" })
- .WithEnvironment(PasswordEnvVarName, () => mySqlContainer.Password);
- }
-
///
/// Adds a MySQL database to the application model.
///
/// The MySQL server resource builder.
/// The name of the resource. This name will be used as the connection string name when referenced in a dependency.
/// A reference to the .
- public static IResourceBuilder AddDatabase(this IResourceBuilder builder, string name)
+ public static IResourceBuilder AddDatabase(this IResourceBuilder builder, string name)
{
var mySqlDatabase = new MySqlDatabaseResource(name, builder.Resource);
return builder.ApplicationBuilder.AddResource(mySqlDatabase)
@@ -82,7 +65,7 @@ public static IResourceBuilder AddDatabase(this IResource
/// The host port for the application ui.
/// The name of the container (Optional).
/// A reference to the .
- public static IResourceBuilder WithPhpMyAdmin(this IResourceBuilder builder, int? hostPort = null, string? containerName = null) where T : IMySqlParentResource
+ public static IResourceBuilder WithPhpMyAdmin(this IResourceBuilder builder, int? hostPort = null, string? containerName = null) where T : MySqlServerResource
{
if (builder.ApplicationBuilder.Resources.OfType().Any())
{
@@ -114,7 +97,17 @@ private static void WriteMySqlDatabaseToManifest(ManifestPublishingContext conte
context.Writer.WriteString("parent", mySqlDatabase.Parent.Name);
}
- private static void WriteMySqlContainerResourceToManifest(ManifestPublishingContext context, MySqlContainerResource resource)
+ ///
+ /// Changes resource to be published as a container.
+ ///
+ /// The builder.
+ /// A reference to the .
+ public static IResourceBuilder PublishAsContainer(this IResourceBuilder builder)
+ {
+ return builder.WithManifestPublishingCallback(context => WriteMySqlContainerResourceToManifest(context, builder.Resource));
+ }
+
+ private static void WriteMySqlContainerResourceToManifest(ManifestPublishingContext context, MySqlServerResource resource)
{
context.WriteContainer(resource);
context.Writer.WriteString( // "connectionString": "...",
diff --git a/src/Aspire.Hosting/MySql/MySqlContainerResource.cs b/src/Aspire.Hosting/MySql/MySqlContainerResource.cs
deleted file mode 100644
index ea0e2daf87..0000000000
--- a/src/Aspire.Hosting/MySql/MySqlContainerResource.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using Aspire.Hosting.Utils;
-
-namespace Aspire.Hosting.ApplicationModel;
-
-///
-/// A resource that represents a MySQL container.
-///
-/// The name of the resource.
-/// The MySQL server root password.
-public class MySqlContainerResource(string name, string password) : ContainerResource(name), IMySqlParentResource
-{
- public string Password { get; } = password;
-
- ///
- /// Gets the connection string for the MySQL server.
- ///
- /// A connection string for the MySQL server in the form "Server=host;Port=port;User ID=root;Password=password".
- public string? GetConnectionString()
- {
- if (!this.TryGetAllocatedEndPoints(out var allocatedEndpoints))
- {
- throw new DistributedApplicationException("Expected allocated endpoints!");
- }
-
- var allocatedEndpoint = allocatedEndpoints.Single(); // We should only have one endpoint for MySQL.
-
- var connectionString = $"Server={allocatedEndpoint.Address};Port={allocatedEndpoint.Port};User ID=root;Password=\"{PasswordUtil.EscapePassword(Password)}\";";
- return connectionString;
- }
-}
diff --git a/src/Aspire.Hosting/MySql/MySqlDatabaseResource.cs b/src/Aspire.Hosting/MySql/MySqlDatabaseResource.cs
index ed6100dee4..3e594841f0 100644
--- a/src/Aspire.Hosting/MySql/MySqlDatabaseResource.cs
+++ b/src/Aspire.Hosting/MySql/MySqlDatabaseResource.cs
@@ -4,13 +4,13 @@
namespace Aspire.Hosting.ApplicationModel;
///
-/// A resource that represents a MySQL database. This is a child resource of a .
+/// A resource that represents a MySQL database. This is a child resource of a .
///
/// The name of the resource.
-/// The MySQL parent resource associated with this database.
-public class MySqlDatabaseResource(string name, IMySqlParentResource mySqlParentResource) : Resource(name), IResourceWithParent, IResourceWithConnectionString
+/// The MySQL parent resource associated with this database.
+public class MySqlDatabaseResource(string name, MySqlServerResource parent) : Resource(name), IResourceWithParent, IResourceWithConnectionString
{
- public IMySqlParentResource Parent { get; } = mySqlParentResource;
+ public MySqlServerResource Parent { get; } = parent;
///
/// Gets the connection string for the MySQL database.
diff --git a/src/Aspire.Hosting/MySql/MySqlServerResource.cs b/src/Aspire.Hosting/MySql/MySqlServerResource.cs
index dff9920f9f..6fca1053b6 100644
--- a/src/Aspire.Hosting/MySql/MySqlServerResource.cs
+++ b/src/Aspire.Hosting/MySql/MySqlServerResource.cs
@@ -10,7 +10,7 @@ namespace Aspire.Hosting.ApplicationModel;
///
/// The name of the resource.
/// The MySQL server root password.
-public class MySqlServerResource(string name, string password) : Resource(name), IMySqlParentResource
+public class MySqlServerResource(string name, string password) : ContainerResource(name), IResourceWithConnectionString
{
public string Password { get; } = password;
diff --git a/src/Aspire.Hosting/MySql/PhpMyAdminConfigWriterHook.cs b/src/Aspire.Hosting/MySql/PhpMyAdminConfigWriterHook.cs
index 57bf52b206..7e3f204863 100644
--- a/src/Aspire.Hosting/MySql/PhpMyAdminConfigWriterHook.cs
+++ b/src/Aspire.Hosting/MySql/PhpMyAdminConfigWriterHook.cs
@@ -11,7 +11,7 @@ public Task AfterEndpointsAllocatedAsync(DistributedApplicationModel appModel, C
{
var adminResource = appModel.Resources.OfType().Single();
var serverFileMount = adminResource.Annotations.OfType().Single(v => v.Target == "/etc/phpmyadmin/config.user.inc.php");
- var mySqlInstances = appModel.Resources.OfType();
+ var mySqlInstances = appModel.Resources.OfType();
if (appModel.Resources.OfType().SingleOrDefault() is not { } myAdminResource)
{
@@ -35,13 +35,7 @@ public Task AfterEndpointsAllocatedAsync(DistributedApplicationModel appModel, C
{
context.EnvironmentVariables.Add("PMA_HOST", $"host.docker.internal:{endpoint.Port}");
context.EnvironmentVariables.Add("PMA_USER", "root");
- var password = singleInstance switch
- {
- MySqlServerResource psr => psr.Password,
- MySqlContainerResource pcr => pcr.Password,
- _ => throw new InvalidOperationException("MySql resource is neither MySqlServerResource or MySqlContainerResource.")
- };
- context.EnvironmentVariables.Add("PMA_PASSWORD", password);
+ context.EnvironmentVariables.Add("PMA_PASSWORD", singleInstance.Password);
}));
}
}
@@ -58,20 +52,13 @@ public Task AfterEndpointsAllocatedAsync(DistributedApplicationModel appModel, C
{
if (mySqlInstance.TryGetAllocatedEndPoints(out var allocatedEndpoints))
{
- var password = mySqlInstance switch
- {
- MySqlServerResource psr => psr.Password,
- MySqlContainerResource pcr => pcr.Password,
- _ => throw new InvalidOperationException("MySql resource is neither MySqlServerResource or MySqlContainerResource.")
- };
-
var endpoint = allocatedEndpoints.Where(ae => ae.Name == "tcp").Single();
writer.WriteLine("$i++;");
writer.WriteLine($"$cfg['Servers'][$i]['host'] = 'host.docker.internal:{endpoint.Port}';");
writer.WriteLine($"$cfg['Servers'][$i]['verbose'] = '{mySqlInstance.Name}';");
writer.WriteLine($"$cfg['Servers'][$i]['auth_type'] = 'cookie';");
writer.WriteLine($"$cfg['Servers'][$i]['user'] = 'root';");
- writer.WriteLine($"$cfg['Servers'][$i]['password'] = '{password}';");
+ writer.WriteLine($"$cfg['Servers'][$i]['password'] = '{mySqlInstance.Password}';");
writer.WriteLine($"$cfg['Servers'][$i]['AllowNoPassword'] = true;");
writer.WriteLine();
}
diff --git a/tests/Aspire.Hosting.Tests/MySql/AddMySqlTests.cs b/tests/Aspire.Hosting.Tests/MySql/AddMySqlTests.cs
index 5dfbfc2e0f..2ed4953698 100644
--- a/tests/Aspire.Hosting.Tests/MySql/AddMySqlTests.cs
+++ b/tests/Aspire.Hosting.Tests/MySql/AddMySqlTests.cs
@@ -15,13 +15,13 @@ public class AddMySqlTests
public void AddMySqlContainerWithDefaultsAddsAnnotationMetadata()
{
var appBuilder = DistributedApplication.CreateBuilder();
- appBuilder.AddMySqlContainer("mysql");
+ appBuilder.AddMySql("mysql");
var app = appBuilder.Build();
var appModel = app.Services.GetRequiredService();
- var containerResource = Assert.Single(appModel.Resources.OfType());
+ var containerResource = Assert.Single(appModel.Resources.OfType());
Assert.Equal("mysql", containerResource.Name);
var manifestAnnotation = Assert.Single(containerResource.Annotations.OfType());
@@ -63,7 +63,7 @@ public void AddMySqlContainerWithDefaultsAddsAnnotationMetadata()
public void AddMySqlAddsAnnotationMetadata()
{
var appBuilder = DistributedApplication.CreateBuilder();
- appBuilder.AddMySqlContainer("mysql", 1234, "pass");
+ appBuilder.AddMySql("mysql", 1234, "pass");
var app = appBuilder.Build();
@@ -111,7 +111,7 @@ public void AddMySqlAddsAnnotationMetadata()
public void MySqlCreatesConnectionString()
{
var appBuilder = DistributedApplication.CreateBuilder();
- appBuilder.AddMySqlContainer("mysql")
+ appBuilder.AddMySql("mysql")
.WithAnnotation(
new AllocatedEndpointAnnotation("mybinding",
ProtocolType.Tcp,
@@ -134,7 +134,7 @@ public void MySqlCreatesConnectionString()
public void MySqlCreatesConnectionStringWithDatabase()
{
var appBuilder = DistributedApplication.CreateBuilder();
- appBuilder.AddMySqlContainer("mysql")
+ appBuilder.AddMySql("mysql")
.WithAnnotation(
new AllocatedEndpointAnnotation("mybinding",
ProtocolType.Tcp,
@@ -148,7 +148,7 @@ public void MySqlCreatesConnectionStringWithDatabase()
var appModel = app.Services.GetRequiredService();
- var mySqlResource = Assert.Single(appModel.Resources.OfType());
+ var mySqlResource = Assert.Single(appModel.Resources.OfType());
var mySqlConnectionString = mySqlResource.GetConnectionString();
var mySqlDatabaseResource = Assert.Single(appModel.Resources.OfType());
var dbConnectionString = mySqlDatabaseResource.GetConnectionString();
@@ -162,7 +162,7 @@ public void WithMySqlTwiceEndsUpWithOneAdminContainer()
{
var builder = DistributedApplication.CreateBuilder();
builder.AddMySql("mySql").WithPhpMyAdmin();
- builder.AddMySqlContainer("mySql2").WithPhpMyAdmin();
+ builder.AddMySql("mySql2").WithPhpMyAdmin();
Assert.Single(builder.Resources.OfType());
}
diff --git a/tests/Aspire.Hosting.Tests/MySql/MySqlContainerResourceTests.cs b/tests/Aspire.Hosting.Tests/MySql/MySqlConnectionStringBuilderTests.cs
similarity index 100%
rename from tests/Aspire.Hosting.Tests/MySql/MySqlContainerResourceTests.cs
rename to tests/Aspire.Hosting.Tests/MySql/MySqlConnectionStringBuilderTests.cs