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

[Enhancement]: Add IConnectionStringProvider for modules / container builder API #1074

Open
HofmeisterAn opened this issue Dec 12, 2023 · 2 comments
Labels
enhancement New feature or request

Comments

@HofmeisterAn
Copy link
Collaborator

Problem

Not all Testcontainers modules represent services that can be exchanged with each other, like ADO.NET compatible modules do. However, usually (almost every time), they offer a method or property (one) that retrieves a connection string or something similar to connect to the service running inside the container.

Occasionally, developers request an additional abstraction to access the connection string of the modules' container. Currently, only ADO.NET compatible containers offer this kind of abstraction. Implementing a default connection string property or method across all modules is not accurate, as the terminologies vary depending on the actual module and service (this is one reason why modules do not offer it yet: ConnectionString, BaseAddress, Endpoint, etc.).

Apart from the absence of this abstraction, modules do not provide connection strings for container to container communication by default. Developers need to create the required connection string themselves. However, modules can at least offer two types of connection strings by default: one for the test-host to container and another for the container to container communication.

Third, developers cannot override the pre-configured connection string.

Solution

Extending the container builder to allow overriding a connection provider enables developers to customize the pre-configured connection string within modules. Moreover, instead of having a single connection string for the test-host to container communication, the provider can provide an additional connection string for container-to-container communication. Lastly, the connection provider serves as an abstraction and can be passed around without exposing the entire container instances (if necessary).

This is the initial concept:

IConnectionStringProvider c1 = new ContainerBuilder()
    .WithConnectionStringProvider(new MyProvider1())
    .Build();

IConnectionStringProvider c2 = new PostgreSqlBuilder()
    .WithConnectionStringProvider(new MyProvider2())
    .Build();

_ = c1.GetConnectionString();

_ = c1.GetConnectionString(ConnectionMode.Host);

_ = c1.GetConnectionString(ConnectionMode.Container);

private sealed class MyProvider1 : IConnectionStringProvider<IContainer, IContainerConfiguration>
{
    public void Build(IContainer container, IContainerConfiguration configuration)
    {
        // TODO: Add connection string for host and container communication.
    }
}

private sealed class MyProvider2 : IConnectionStringProvider<PostgreSqlContainer, PostgreSqlConfiguration>
{
    public void Build(PostgreSqlContainer container, PostgreSqlConfiguration configuration)
    {
        // TODO: Add connection string for host and container communication.
    }
}

Please note that since the IConnectionStringProvider interface serves as the minimal common denominator, it cannot provide additional public, module-specific properties and methods. If such properties or methods are necessary, the specific type must be used.

This issue relates to:

Benefit

Offers additional configurations developers can utilize to configure their test case/scenario.

Alternatives

-

Would you like to help contributing this enhancement?

Yes

@HofmeisterAn HofmeisterAn added the enhancement New feature or request label Dec 12, 2023
@HofmeisterAn
Copy link
Collaborator Author

HofmeisterAn commented Dec 12, 2023

Please note that since the IConnectionStringProvider interface serves as the minimal common denominator, it cannot provide additional public, module-specific properties and methods. If such properties or methods are necessary, the specific type must be used.

The actual implementation of the connection provider is pretty simple and straightforward. However, before implementing and finalizing it, I would like to consider the different possibilities we have to provide the most convenient API. One that offers the mentioned abstraction to share the container instances and provide access to its connection string, and one that also allows access to more detailed implementations if necessary (e.g. we need for Minio, Redpanda, etc.).

@mrudat
Copy link

mrudat commented May 14, 2024

Would it be better to have:

public interface IJdbcConnectionStringSource : IConnectionStringSource

or

class PostgresqlContainer : IConnectionStringSource<IJdbcConnectionString>, IConnectionStringSource<IAdoConnectionString>, ...

?

What about protocols that are not enabled by default?

Would calling .WithXProtocol, which then calls .GetXConnectionString, cause X to be enabled?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants