-
Notifications
You must be signed in to change notification settings - Fork 717
Add Aspire.MySqlConnector #825
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
abb3d0b
0c3f020
1deac05
b6a5e0e
3255804
5b16736
ca9ef22
9f85ccf
68077a2
b1c30a9
a64653f
4ad05e2
28c84fa
ec14198
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| // 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; | ||
|
|
||
| /// <summary> | ||
| /// Represents a MySQL resource that requires a connection string. | ||
| /// </summary> | ||
| public interface IMySqlResource : IResourceWithConnectionString | ||
| { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.Net.Sockets; | ||
| using System.Text.Json; | ||
| using Aspire.Hosting.ApplicationModel; | ||
|
|
||
| namespace Aspire.Hosting; | ||
|
|
||
| /// <summary> | ||
| /// Provides extension methods for adding MySQL resources to an <see cref="IDistributedApplicationBuilder"/>. | ||
| /// </summary> | ||
| public static class MySqlBuilderExtensions | ||
| { | ||
| private const string PasswordEnvVarName = "MYSQL_ROOT_PASSWORD"; | ||
|
|
||
| /// <summary> | ||
| /// Adds a MySQL container to the application model. The default image is "mysql" and the tag is "latest". | ||
| /// </summary> | ||
| /// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param> | ||
| /// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param> | ||
| /// <param name="port">The host port for MySQL.</param> | ||
| /// <param name="password">The password for the MySQL root user. Defaults to a random password.</param> | ||
| /// <returns>A reference to the <see cref="IResourceBuilder{MySqlContainerResource}"/>.</returns> | ||
| public static IResourceBuilder<MySqlContainerResource> AddMySqlContainer(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) | ||
| .WithAnnotation(new ManifestPublishingCallbackAnnotation(WriteMySqlContainerToManifest)) | ||
| .WithAnnotation(new ServiceBindingAnnotation(ProtocolType.Tcp, port: port, containerPort: 3306)) // Internal port is always 3306. | ||
| .WithAnnotation(new ContainerImageAnnotation { Image = "mysql", Tag = "latest" }) | ||
| .WithEnvironment(PasswordEnvVarName, () => mySqlContainer.Password); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Adds a MySQL connection to the application model. Connection strings can also be read from the connection string section of the configuration using the name of the resource. | ||
| /// </summary> | ||
| /// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param> | ||
| /// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param> | ||
| /// <param name="connectionString">The MySQL connection string (optional).</param> | ||
| /// <returns>A reference to the <see cref="IResourceBuilder{MySqlConnectionResource}"/>.</returns> | ||
| public static IResourceBuilder<MySqlConnectionResource> AddMySqlConnection(this IDistributedApplicationBuilder builder, string name, string? connectionString = null) | ||
| { | ||
| var mySqlConnection = new MySqlConnectionResource(name, connectionString); | ||
|
|
||
| return builder.AddResource(mySqlConnection) | ||
| .WithAnnotation(new ManifestPublishingCallbackAnnotation((json) => WriteMySqlConnectionToManifest(json, mySqlConnection))); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Adds a MySQL database to the application model. | ||
| /// </summary> | ||
| /// <param name="builder">The MySQL server resource builder.</param> | ||
| /// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param> | ||
| /// <returns>A reference to the <see cref="IResourceBuilder{MySqlDatabaseResource}"/>.</returns> | ||
| public static IResourceBuilder<MySqlDatabaseResource> AddDatabase(this IResourceBuilder<MySqlContainerResource> builder, string name) | ||
| { | ||
| var mySqlDatabase = new MySqlDatabaseResource(name, builder.Resource); | ||
| return builder.ApplicationBuilder.AddResource(mySqlDatabase) | ||
| .WithAnnotation(new ManifestPublishingCallbackAnnotation( | ||
| (json) => WriteMySqlDatabaseToManifest(json, mySqlDatabase))); | ||
| } | ||
|
|
||
| private static void WriteMySqlConnectionToManifest(Utf8JsonWriter jsonWriter, MySqlConnectionResource mySqlConnection) | ||
| { | ||
| jsonWriter.WriteString("type", "mysql.connection.v0"); | ||
| jsonWriter.WriteString("connectionString", mySqlConnection.GetConnectionString()); | ||
| } | ||
|
|
||
| private static void WriteMySqlContainerToManifest(Utf8JsonWriter jsonWriter) | ||
| { | ||
| jsonWriter.WriteString("type", "mysql.server.v0"); | ||
| } | ||
|
|
||
| private static void WriteMySqlDatabaseToManifest(Utf8JsonWriter json, MySqlDatabaseResource mySqlDatabase) | ||
| { | ||
| json.WriteString("type", "mysql.database.v0"); | ||
| json.WriteString("parent", mySqlDatabase.Parent.Name); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| // 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; | ||
|
|
||
| /// <summary> | ||
| /// A resource that represents a MySQL connection. | ||
| /// </summary> | ||
| /// <param name="name">The name of the resource.</param> | ||
| /// <param name="connectionString">The MySQL connection string.</param> | ||
| public class MySqlConnectionResource(string name, string? connectionString) : Resource(name), IMySqlResource | ||
| { | ||
| private readonly string? _connectionString = connectionString; | ||
|
|
||
| /// <summary> | ||
| /// Gets the connection string for the MySQL server. | ||
| /// </summary> | ||
| /// <returns>The specified connection string.</returns> | ||
| public string? GetConnectionString() => _connectionString; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| // 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; | ||
|
|
||
| /// <summary> | ||
| /// A resource that represents a MySQL container. | ||
| /// </summary> | ||
| /// <param name="name">The name of the resource.</param> | ||
| /// <param name="password">The MySQL server root password.</param> | ||
| public class MySqlContainerResource(string name, string password) : ContainerResource(name), IMySqlResource | ||
| { | ||
| public string Password { get; } = password; | ||
|
|
||
| /// <summary> | ||
| /// Gets the connection string for the MySQL server. | ||
| /// </summary> | ||
| /// <returns>A connection string for the MySQL server in the form "Host=host;Port=port;Username=root;Password=password".</returns> | ||
| 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 = $"Host={allocatedEndpoint.Address};Port={allocatedEndpoint.Port};Username=root;Password={Password};"; | ||
| return connectionString; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| // 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; | ||
|
|
||
| /// <summary> | ||
| /// A resource that represents a MySQL database. This is a child resource of a <see cref="MySqlContainerResource"/>. | ||
| /// </summary> | ||
| /// <param name="name">The name of the resource.</param> | ||
| /// <param name="mySqlContainer">The MySQL server resource associated with this database.</param> | ||
| public class MySqlDatabaseResource(string name, MySqlContainerResource mySqlContainer) : Resource(name), IMySqlResource, IResourceWithParent<MySqlContainerResource> | ||
| { | ||
| public MySqlContainerResource Parent { get; } = mySqlContainer; | ||
|
|
||
| /// <summary> | ||
| /// Gets the connection string for the MySQL database. | ||
| /// </summary> | ||
| /// <returns>A connection string for the MySQL database.</returns> | ||
| public string? GetConnectionString() | ||
| { | ||
| if (Parent.GetConnectionString() is { } connectionString) | ||
| { | ||
| return $"{connectionString}Database={Name}"; | ||
| } | ||
| else | ||
| { | ||
| throw new DistributedApplicationException("Parent resource connection string was null."); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @eerhardt should we start moving these things to a resx? I assume we won't localize unless the base libraries start to localize. So perhaps there isn't much value. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ASP.NET Core doesn't have a lot of its exception messages in resx's either. For example If we ever needed to localize our exceptions, it wouldn't be that hard to find these. But odds are, after 8 years of .NET Core System.* libraries not being localized, I'd be surprised if it ever happens. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. |
||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <TargetFramework>$(NetCurrent)</TargetFramework> | ||
| <IsPackable>true</IsPackable> | ||
| <PackageTags>$(ComponentDatabasePackageTags) mysqlconnector mysql sql</PackageTags> | ||
| <Description>A MySQL client that integrates with Aspire, including health checks, metrics, logging, and telemetry.</Description> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does MySQL need a |
||
| <PackageIconFullPath>$(SharedDir)SQL_256x.png</PackageIconFullPath> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @DamianEdwards - should this have the same icon as the https://www.nuget.org/packages/MySqlConnector/ package? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would be ideal, assuming we have permission to do so 😀 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I created the MySqlConnector package icon (using free sources) and will give any necessary permission to include it here. |
||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <Compile Include="..\Common\HealthChecksExtensions.cs" Link="HealthChecksExtensions.cs" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="AspNetCore.HealthChecks.MySql" /> | ||
| <PackageReference Include="Microsoft.Extensions.Configuration.Binder" /> | ||
| <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" /> | ||
| <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" /> | ||
| <PackageReference Include="MySqlConnector.DependencyInjection" /> | ||
| <PackageReference Include="OpenTelemetry.Extensions.Hosting" /> | ||
| </ItemGroup> | ||
|
|
||
| </Project> | ||

Uh oh!
There was an error while loading. Please reload this page.