Skip to content
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

Extract Aspire.Hosting.MySql.Tests #4925

Merged
merged 18 commits into from
Jul 20, 2024
Merged

Extract Aspire.Hosting.MySql.Tests #4925

merged 18 commits into from
Jul 20, 2024

Conversation

sebastienros
Copy link
Member

@sebastienros sebastienros commented Jul 16, 2024

Contributes to #4294

Microsoft Reviewers: Open in CodeFlow

@sebastienros sebastienros requested review from eerhardt and removed request for mitchdenny July 16, 2024 08:07
@dotnet-issue-labeler dotnet-issue-labeler bot added the area-codeflow for labeling automated codeflow. intentionally a different color! label Jul 16, 2024
Copy link
Member

@eerhardt eerhardt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also remove MySql from the EndToEnd tests?

If we do, we should probably have 2 functional tests - one for the non-EF component and one for the EF component. It could be in a single test if we wanted.

Comment on lines 15 to 16
<Compile Include="$(SharedDir)SecretsStore.cs" Link="Utils\SecretsStore.cs" />
<Compile Include="$(RepoRoot)src\Aspire.Hosting\ApplicationModel\UserSecretsParameterDefault.cs" Link="Utils\UserSecretsParameterDefault.cs" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are these for?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are tests checking that this is the type of credential that is created with the resource.
For all DBs btw.

AddMySqlAddsGeneratedPasswordParameterWithUserSecretsParameterDefaultInRunMode
AddMySqlDoesNotAddGeneratedPasswordParameterWithUserSecretsParameterDefaultInPublishMode

These are adapted though since the actual instance type is from the internal type in the Hosting assembly, and not the local one. What would solve it would be to make the type public.

@@ -59,6 +57,7 @@
<Compile Include="$(RepoRoot)src\Aspire.Hosting.Nats\NatsContainerImageTags.cs" />
<Compile Include="$(RepoRoot)src\Aspire.Hosting.Milvus\MilvusContainerImageTags.cs" />
<Compile Include="$(RepoRoot)src\Aspire.Hosting.MongoDB\MongoDBContainerImageTags.cs" />
<Compile Include="$(RepoRoot)src\Aspire.Hosting.MySql\MySqlContainerImageTags.cs" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this still used for? It seems like it should be removed. Aspire.Hosting.Tests shouldn't need to be testing all the extension resources we create.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VerifyTestProgramFullManifest checks a manifest which has all these resources, and uses

"image": "{{TestConstants.AspireTestContainerRegistry}}/{{MySqlContainerImageTags.Image}}:{{MySqlContainerImageTags.Tag}}",

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this line should be removed.

@radical
Copy link
Member

radical commented Jul 16, 2024

MySqlConnector.MySqlException : Couldn't connect to server
---- MySqlConnector.MySqlEndOfStreamException : An incomplete response was received from the server

CallStack
   at MySqlConnector.Core.ServerSession.ConnectAsync(ConnectionSettings cs, MySqlConnection connection, Int64 startingTimestamp, ILoadBalancer loadBalancer, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/ServerSession.cs:line 564
   at MySqlConnector.Core.ConnectionPool.ConnectSessionAsync(MySqlConnection connection, Action`4 logMessage, Int64 startingTimestamp, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/ConnectionPool.cs:line 428
   at MySqlConnector.Core.ConnectionPool.ConnectSessionAsync(MySqlConnection connection, Action`4 logMessage, Int64 startingTimestamp, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/ConnectionPool.cs:line 433
   at MySqlConnector.Core.ConnectionPool.GetSessionAsync(MySqlConnection connection, Int64 startingTimestamp, Int32 timeoutMilliseconds, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/ConnectionPool.cs:line 111
   at MySqlConnector.Core.ConnectionPool.GetSessionAsync(MySqlConnection connection, Int64 startingTimestamp, Int32 timeoutMilliseconds, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/ConnectionPool.cs:line 144
   at MySqlConnector.MySqlConnection.CreateSessionAsync(ConnectionPool pool, Int64 startingTimestamp, Activity activity, Nullable`1 ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlConnection.cs:line 1054
   at MySqlConnector.MySqlConnection.OpenAsync(Nullable`1 ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlConnection.cs:line 554
   at Aspire.Hosting.MySql.Tests.MySqlFunctionalTests.<>c__DisplayClass3_0.<<WithDataShouldPersistStateBetweenUsages>b__0>d.MoveNext() in /_/tests/Aspire.Hosting.MySql.Tests/MySqlFunctionalTests.cs:line 129
--- End of stack trace from previous location ---
   at Polly.ResiliencePipeline.<>c.<<ExecuteAsync>b__3_0>d.MoveNext()
--- End of stack trace from previous location ---
   at Polly.Outcome`1.GetResultOrRethrow()
   at Polly.ResiliencePipeline.ExecuteAsync(Func`2 callback, CancellationToken cancellationToken)
   at Aspire.Hosting.MySql.Tests.MySqlFunctionalTests.WithDataShouldPersistStateBetweenUsages(Boolean useVolume) in /_/tests/Aspire.Hosting.MySql.Tests/MySqlFunctionalTests.cs:line 126
   at Aspire.Hosting.MySql.Tests.MySqlFunctionalTests.WithDataShouldPersistStateBetweenUsages(Boolean useVolume) in /_/tests/Aspire.Hosting.MySql.Tests/MySqlFunctionalTests.cs:line 142
--- End of stack trace from previous location ---
----- Inner Stack Trace -----
   at MySqlConnector.Protocol.Serialization.ProtocolUtility.ReadPayloadAsync(BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func`1 getNextSequenceNumber, ArraySegmentHolder`1 previousPayloads, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) in /_/src/MySqlConnector/Protocol/Serialization/ProtocolUtility.cs:line 424
   at MySqlConnector.Core.ServerSession.ReceiveReplyAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/ServerSession.cs:line 880
   at MySqlConnector.Core.ServerSession.ConnectAsync(ConnectionSettings cs, MySqlConnection connection, Int64 startingTimestamp, ILoadBalancer loadBalancer, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/ServerSession.cs:line 445

@radical radical added area-integrations Issues pertaining to Aspire Integrations packages and removed area-codeflow for labeling automated codeflow. intentionally a different color! labels Jul 16, 2024
<ItemGroup>
<Compile Include="$(SharedDir)SecretsStore.cs" Link="Utils\SecretsStore.cs" />
<Compile Include="$(RepoRoot)src\Aspire.Hosting\ApplicationModel\UserSecretsParameterDefault.cs" Link="Utils\UserSecretsParameterDefault.cs" />
<Compile Include="$(RepoRoot)src\Aspire.Hosting.Testing\ResourceLoggerForwarderService.cs" Link="Utils\ResourceLoggerForwarderService.cs" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should be compiling this into our tests. If we need this, we should just reference Aspire.Hosting.Testing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied in another PR, copied here.

<ProjectReference Include="..\..\src\Aspire.Hosting.Nats\Aspire.Hosting.Nats.csproj" IsAspireProjectResource="false" />
<ProjectReference Include="..\..\src\Aspire.Hosting.Testing\Aspire.Hosting.Testing.csproj" IsAspireProjectResource="false" />
<ProjectReference Include="..\Aspire.Components.Common.Tests\Aspire.Components.Common.Tests.csproj" IsAspireProjectResource="false" />
<ProjectReference Include="..\testproject\TestProject.AppHost\TestProject.AppHost.csproj" IsAspireProjectResource="false" />
<ProjectReference Include="..\Aspire.Hosting.Tests.SharedShim\Aspire.Hosting.Tests.SharedShim.csproj" IsAspireProjectResource="false" Aliases="AspireHostingShared" />
<ProjectReference Include="..\..\src\Components\Aspire.Microsoft.Data.SqlClient\Aspire.Microsoft.Data.SqlClient.csproj" IsAspireProjectResource="false" />
<ProjectReference Include="..\..\src\Components\Aspire.MongoDB.Driver\Aspire.MongoDB.Driver.csproj" IsAspireProjectResource="false" />
<ProjectReference Include="..\..\src\Components\Aspire.Npgsql\Aspire.Npgsql.csproj" IsAspireProjectResource="false" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we adding Npgsql in a MySql PR?

I think this should be removed.

@@ -59,6 +57,7 @@
<Compile Include="$(RepoRoot)src\Aspire.Hosting.Nats\NatsContainerImageTags.cs" />
<Compile Include="$(RepoRoot)src\Aspire.Hosting.Milvus\MilvusContainerImageTags.cs" />
<Compile Include="$(RepoRoot)src\Aspire.Hosting.MongoDB\MongoDBContainerImageTags.cs" />
<Compile Include="$(RepoRoot)src\Aspire.Hosting.MySql\MySqlContainerImageTags.cs" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this line should be removed.

[$"ConnectionStrings:{db.Resource.Name}"] = await db.Resource.ConnectionStringExpression.GetValueAsync(default)
});

hb.AddMySqlDataSource(db.Resource.Name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also have tests that use the EF component? That way we can remove MySql from the EndToEnd tests completely and not lose coverage.

Copy link
Member Author

@sebastienros sebastienros Jul 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the EF tests here. Very similar to the one I did with Oracle (creating the tables using EF too, not just a SELECT 1 like in E2E).

Comment on lines 86 to 90
var password = "p@ssw0rd1";

var passwordParameter = builder1.AddParameter("pwd");
builder1.Configuration["Parameters:pwd"] = password;
var mysql1 = builder1.AddMySql("mysql", passwordParameter).WithEnvironment("MYSQL_DATABASE", mySqlDbName);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of hard-coding a password (and cause more cred scan issues), can we use ParameterResourceBuilderExtensions.CreateDefaultPasswordParameter instead?

/// <summary>
/// Creates a default password parameter that generates a random password.
/// </summary>
/// <param name="builder">Distributed application builder</param>
/// <param name="name">Name of parameter resource</param>
/// <param name="lower"><see langword="true" /> if lowercase alphabet characters should be included; otherwise, <see langword="false" />.</param>
/// <param name="upper"><see langword="true" /> if uppercase alphabet characters should be included; otherwise, <see langword="false" />.</param>
/// <param name="numeric"><see langword="true" /> if numeric characters should be included; otherwise, <see langword="false" />.</param>
/// <param name="special"><see langword="true" /> if special characters should be included; otherwise, <see langword="false" />.</param>
/// <param name="minLower">The minimum number of lowercase characters in the result.</param>
/// <param name="minUpper">The minimum number of uppercase characters in the result.</param>
/// <param name="minNumeric">The minimum number of numeric characters in the result.</param>
/// <param name="minSpecial">The minimum number of special characters in the result.</param>
/// <returns>The created <see cref="ParameterResource"/>.</returns>
/// <remarks>
/// To ensure the generated password has enough entropy, see the remarks in <see cref="GenerateParameterDefault"/>.<br/>
/// The value will be saved to the app host project's user secrets store when <see cref="DistributedApplicationExecutionContext.IsRunMode"/> is <c>true</c>.
/// </remarks>
public static ParameterResource CreateDefaultPasswordParameter(
IDistributedApplicationBuilder builder, string name,
bool lower = true, bool upper = true, bool numeric = true, bool special = true,
int minLower = 0, int minUpper = 0, int minNumeric = 0, int minSpecial = 0)
{

@sebastienros
Copy link
Member Author

sebastienros commented Jul 19, 2024

@eerhardt @radical fyi what was making the only test to fail was to use a bindmountpath which was not created before the container starts. It seems some containers are fine with that (Kafka?). But this would work locally just fine. Maybe some other kind of permissions, where locally the instance can create the folder, but not on the CI.

@eerhardt eerhardt enabled auto-merge (squash) July 19, 2024 23:03
Copy link
Member

@radical radical left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than the one comment, LGTM 👍

.AddRetry(new() { MaxRetryAttempts = 10, BackoffType = DelayBackoffType.Linear, Delay = TimeSpan.FromSeconds(2), ShouldHandle = new PredicateBuilder().Handle<MySqlException>() })
.Build();

var bindMountPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to use Directory.CreateTempSubdirectory().FullName here too, and skip the need to delete+create the directory below?

@eerhardt eerhardt merged commit 5238a73 into main Jul 20, 2024
9 checks passed
@eerhardt eerhardt deleted the sebros/mysqltests branch July 20, 2024 01:00
radical pushed a commit that referenced this pull request Jul 26, 2024
* Extract Aspire.Hosting.MySql.Tests

* Improve reliability

* Record Docker logs

* Fix ResourceLoggerForwarderService link in Aspire.Hosting.PostgreSQL.csproj

* Remove E2E tests

* Fix manifest test

* Fix tests

* Increase delay between retries

* Create mount path directory

* Address PR feedback

* Use Directory.Delete

* Use Linear backoff

---------

Co-authored-by: Ankit Jain <[email protected]>
Co-authored-by: Eric Erhardt <[email protected]>
(cherry picked from commit 5238a73)
@github-actions github-actions bot locked and limited conversation to collaborators Aug 19, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-integrations Issues pertaining to Aspire Integrations packages
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants