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

Change how container connection strings resolve the right endpoint #844

Closed
AndyVanDePutte opened this issue Nov 15, 2023 · 12 comments · Fixed by #2596
Closed

Change how container connection strings resolve the right endpoint #844

AndyVanDePutte opened this issue Nov 15, 2023 · 12 comments · Fixed by #2596
Assignees
Labels
area-app-model Issues pertaining to the APIs in Aspire.Hosting, e.g. DistributedApplication bug Something isn't working

Comments

@AndyVanDePutte
Copy link

AndyVanDePutte commented Nov 15, 2023

We should change how allocation endpoints are determine the connection string by using an endpoint called "default" instead of using SingleOfDefault everywhere.

Original Issue

Hi,

I have an Aspire application with an sql-container:


private static void Main(string[] args)
    {
        var builder = DistributedApplication.CreateBuilder(args);

        #region Sql Server Container

        var dbserver = builder.AddSqlServerContainer("sql");
        var emadb = dbserver.AddDatabase("EmaDb");
        var shopdb = dbserver.AddDatabase("ShopDb");
        
        dbserver.WithServiceBinding(1433, 1433);

        #endregion

        //builder.AddProject<Projects.AVDP_MyTicket_EventWorkerService>("eventworkerservice")
        //    .WithReference(emadb)
        //    .WithReference(shopdb);

        var app = builder.Build();
        app.Run();
    }

The container with the sql server is created and because of "dbserver.WithServiceBinding(1433, 1433)" I can connect with my SSMS to this database...

But once I uncomment the 3 lines (with the .WithReference to the databases), it gives me errors on the app.Run().
When I comment out 'dbserver.WithServiceBinding(1433, 1433)', the app is working, but I'm not able to connect with SSMS anymore to the database.

So my question is: what is the correct way to open the 1433 port on the sql container to be availabe on the host machine (in ssms for example).

thx a lot
Andy

@DamianEdwards DamianEdwards added the area-app-model Issues pertaining to the APIs in Aspire.Hosting, e.g. DistributedApplication label Nov 15, 2023
@davidfowl
Copy link
Member

You said "it gives me errors" , what errors?

@AndyVanDePutte
Copy link
Author

AndyVanDePutte commented Nov 16, 2023

You said "it gives me errors" , what errors?

Well.. I simplified the application.. When I start with the .NET Aspire Starter application and update the following code in the AppHost program.cs: file

var dbserver = builder.AddSqlServerContainer("sql");
var shopdb = dbserver.AddDatabase("ShopDb");

dbserver.WithServiceBinding(1433, 1433);

var apiservice = builder
    .AddProject<Projects.AspireApp1_ApiService>("apiservice")
    .WithReference(shopdb);

var app = builder.Build();
app.Run();

receive the following error:

info: Aspire.Dashboard.DashboardWebApplication[0]
      Now listening on: http://localhost:15069
info: Aspire.Dashboard.DashboardWebApplication[0]
      OTLP server running at: http://localhost:16254
fail: Microsoft.Extensions.Hosting.Internal.Host[11]
      Hosting failed to start
      System.InvalidOperationException: Sequence contains more than one element
         at System.Linq.ThrowHelper.ThrowMoreThanOneElementException()
         at System.Linq.Enumerable.TryGetSingle[TSource](IEnumerable`1 source, Boolean& found)
         at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
         at Aspire.Hosting.ApplicationModel.SqlServerContainerResource.GetConnectionString() in /_/src/Aspire.Hosting/SqlServer/SqlServerContainerResource.cs:line 29
         at Aspire.Hosting.ApplicationModel.SqlServerDatabaseResource.GetConnectionString() in /_/src/Aspire.Hosting/SqlServer/SqlServerDatabaseResource.cs:line 25
         at Aspire.Hosting.ResourceBuilderExtensions.<>c__DisplayClass7_0`1.<WithReference>b__0(EnvironmentCallbackContext context) in /_/src/Aspire.Hosting/Extensions/ResourceBuilderExtensions.cs:line 136
         at Aspire.Hosting.Dcp.ApplicationExecutor.CreateExecutablesAsync(IEnumerable`1 executableResources, CancellationToken cancellationToken) in /_/src/Aspire.Hosting/Dcp/ApplicationExecutor.cs:line 397
         at Aspire.Hosting.Dcp.ApplicationExecutor.CreateContainersAndExecutablesAsync(CancellationToken cancellationToken) in /_/src/Aspire.Hosting/Dcp/ApplicationExecutor.cs:line 150
         at Aspire.Hosting.Dcp.ApplicationExecutor.RunApplicationAsync(CancellationToken cancellationToken) in /_/src/Aspire.Hosting/Dcp/ApplicationExecutor.cs:line 75
         at Aspire.Hosting.Dcp.DcpHostService.StartAsync(CancellationToken cancellationToken) in /_/src/Aspire.Hosting/Dcp/DcpHostService.cs:line 78
         at Microsoft.Extensions.Hosting.Internal.Host.<StartAsync>b__15_1(IHostedService service, CancellationToken token)
         at Microsoft.Extensions.Hosting.Internal.Host.ForeachService[T](IEnumerable`1 services, CancellationToken token, Boolean concurrent, Boolean abortOnFirstException, List`1 exceptions, Func`3 operation)
Could not stop project 'apiservice': k8s.Autorest.HttpOperationException: Operation returned an invalid status code 'NotFound', response body {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"executables.usvc-dev.developer.microsoft.com \"apiservice\" not found","reason":"NotFound","details":{"name":"apiservice","group":"usvc-dev.developer.microsoft.com","kind":"executables"},"code":404}

   at k8s.Kubernetes.SendRequestRaw(String requestContent, HttpRequestMessage httpRequest, CancellationToken cancellationToken)
   at k8s.AbstractKubernetes.k8s.ICustomObjectsOperations.DeleteClusterCustomObjectWithHttpMessagesAsync(String group, String version, String plural, String name, V1DeleteOptions body, Nullable`1 gracePeriodSeconds, Nullable`1 orphanDependents, String propagationPolicy, String dryRun, IReadOnlyDictionary`2 customHeaders, CancellationToken cancellationToken)
   at Aspire.Hosting.Dcp.KubernetesService.<>c__DisplayClass12_0`1.<<DeleteAsync>b__0>d.MoveNext() in /_/src/Aspire.Hosting/Dcp/KubernetesService.cs:line 109
--- End of stack trace from previous location ---
   at Aspire.Hosting.Dcp.KubernetesService.ExecuteWithRetry[TResult](DcpApiOperationType operationType, String resourceType, Func`2 operation, CancellationToken cancellationToken) in /_/src/Aspire.Hosting/Dcp/KubernetesService.cs:line 198
   at Aspire.Hosting.Dcp.ApplicationExecutor.DeleteResourcesAsync[RT](String resourceName, CancellationToken cancellationToken) in /_/src/Aspire.Hosting/Dcp/ApplicationExecutor.cs:line 633

Docker Desktop 4.25.1
Windows 11 22H2
Microsoft Visual Studio Professional 2022 (64-bit) - Version 17.9.0 Preview 1.0

@AndyVanDePutte
Copy link
Author

AndyVanDePutte commented Nov 16, 2023

When playing around with it... when I specify a host-port when adding the sql container, It all works...

var dbserver = builder.AddSqlServerContainer("sql", "VerySecretPassword", 1433);

I was not aware that 1433 was not the default (internal) port, but a random port was assigned.

Thx a lot!

@murh-lego
Copy link

You said "it gives me errors" , what errors?

When you configure service binding such as

var rabbit = builder.AddRabbitMQContainer("rabbit")
.WithServiceBinding(5672, 5672)
.WithServiceBinding(15672, 15672);

var sql = builder.AddSqlServerContainer("sql")
.WithServiceBinding(1433, 1433);

Calls to GetConnectionString to each of the container resources will throw because of allocated endpoints

image

I'm probably understanding this wrong :D So please do help :D

Me as I guess the author of this issue wanted to expose these standard ports so I can have it uniformly the same, and not have to see what my dynamically allocated ports are from the dashboard or peeking into environment variables

@davidfowl
Copy link
Member

The built in overloads support a "port" parameter which maps to the host port. Adding more bindings to those will make connection string resolution fail (as currently implemented). We could make this not fail by looking for a specific endpoint binding, but it doesn't change "how" you make this work.

@davidfowl
Copy link
Member

davidfowl commented Dec 6, 2023

cc @mitchdenny should we do something here? Most of our containers would fail like this in connection string resolution.

@davidfowl davidfowl reopened this Dec 6, 2023
@mitchdenny
Copy link
Member

There are a few choices here. The first is that we could simply change the GetConnectionString(...) methods to be more forgiving of having multiple allocated endpoints and instead find the endpoint based on the binding name. Another option is that we make connection string generation somewhat pluggable (which we may need to do anyway).

@davidfowl
Copy link
Member

There are a few choices here. The first is that we could simply change the GetConnectionString(...) methods to be more forgiving of having multiple allocated endpoints and instead find the endpoint based on the binding name

This is what I think we should be doing.

@mitchdenny mitchdenny added this to the preview 3 (Feb) milestone Jan 11, 2024
@mitchdenny mitchdenny added the bug Something isn't working label Jan 11, 2024
@mitchdenny mitchdenny self-assigned this Jan 11, 2024
@davidfowl
Copy link
Member

@JamesNK this is a good one for P4

@davidfowl
Copy link
Member

@BrennanConroy moving to you

@davidfowl
Copy link
Member

Moved to P5

@davidfowl davidfowl changed the title How to expose the port (1433) from an sql container to the host machine? Change how container connection strings resolve the right endpoint Feb 24, 2024
@davidfowl davidfowl assigned davidfowl and unassigned BrennanConroy Mar 3, 2024
@davidfowl
Copy link
Member

All container resources now use a named endpoint as their default and that's what the connection string is based on.

@github-actions github-actions bot locked and limited conversation to collaborators Apr 29, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-app-model Issues pertaining to the APIs in Aspire.Hosting, e.g. DistributedApplication bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants