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

Fix port/targetport fallback logic in proxyless path #4226

Merged
merged 4 commits into from
May 22, 2024

Conversation

davidebbo
Copy link
Contributor

@davidebbo davidebbo commented May 18, 2024

Fixes #4225

Microsoft Reviewers: Open in CodeFlow

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-app-model Issues pertaining to the APIs in Aspire.Hosting, e.g. DistributedApplication label May 18, 2024
@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label May 18, 2024
// It also depends on what the EndpointAnnotation is applied to.
// In the Container case the TargetPort is the port that the process listens on inside the container,
// and the Port is the host interface port, so it is fine for them to be different.
get => _port ?? (IsProxied ? null : _targetPort);
Copy link
Member

Choose a reason for hiding this comment

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

I am not sure about this change... this is going to result in pretty weird behavior for a settable property:

var e = new EndpointAnnotation(ProtocolType.Tcp, port: 1234, targetPort: null, isProxied: false);
Console.WriteLine(e.TargetPort); // prints 1234
e.TargetPort = 4567;
Console.WriteLine(e.TargetPort); // prints 4567
e.TargetPort = null;
Console.WriteLine(e.TargetPort); // prints 1234
e.IsProxied = true;
Console.WriteLine(e.TargetPort); // prints null

Copy link
Member

Choose a reason for hiding this comment

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

I was thinking the same thing. This is basically a way to get torn state. Maybe we need a gross internal method that used in the WithEndpoint callback...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Internal method was my first thought, but it felt a bit dirty to have logic outside of EndpointAnnotation. And it opens the possibility that some new scenario creates an EndpointAnnotation and forgets to call it, leading to inconsistent fallback behavior.

An alternative is to add _portSettingCalled/_targetPortSettingCalled fields to disable the fallback if the setter was ever called.

Let me know which way you prefer, I can do either.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I made a change along those lines. It's a bit more convoluted than I would have liked, but maybe still better than an internal method called from the outside. I also extended the tests to cover setting to null. PTAL.

@karolz-ms karolz-ms requested a review from mitchdenny May 20, 2024 16:00
Copy link
Member

@karolz-ms karolz-ms left a comment

Choose a reason for hiding this comment

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

I can live with this, thanks @davidebbo

@mitchdenny
Copy link
Member

I don't think we can easily change this now, but one alternative we could have taken here is have ProxiedEndpointAnnotation and EndpointAnnotation since they can have slightly different shapes and then use the type system to define the behavior.

@mitchdenny
Copy link
Member

Its ugly but I can't think of a way that is necessarily better.

@davidebbo
Copy link
Contributor Author

I don't think we can easily change this now, but one alternative we could have taken here is have ProxiedEndpointAnnotation and EndpointAnnotation since they can have slightly different shapes and then use the type system to define the behavior.

That would mean not allowing IsProxied to be settable, though that would probably not be a bad thing. It seems strange to allow it to change on a given instance. Anyway, as you say it seems too drastic a change now.

@davidfowl davidfowl merged commit b88cc07 into dotnet:main May 22, 2024
8 checks passed
radical pushed a commit to radical/aspire that referenced this pull request May 22, 2024
* Fix port/targetport fallback logic in proxyless path

Fixes dotnet#4225

* Add tests for port/targetport logic

* Allow caller to set Port/TargetPort to null

* Make the tests cover more scenarios
@davidebbo
Copy link
Contributor Author

So it turns out that this change breaks the test ProxylessContainerWithoutPortThrows. This test has:

        var redis = builder.AddRedis("redis").WithEndpoint("tcp", endpoint =>
        {
            endpoint.IsProxied = false;
        });

Note that it sets a TargetPort in AddRedis, but no Port. With the old logic, the fallback from TargetPort to Port would not happen, because IsProxied is set later. With the new logic, the fallback happens, causing the test to not throw, and hence fail.

My take is that the new behavior is more correct, and that we should just adjust the test to have:

        var redis = builder.AddRedis("redis").WithEndpoint("tcp", endpoint =>
        {
            endpoint.IsProxied = false;
            endpoint.Port = null;
        });

Since clearly the intent of the test is to have no Port.

@davidfowl @karolz-ms @mitchdenny do you agree?

Also, kind of concerning that this was not caught earlier. I guess this test doesn't really run anywhere in an automated way?

@davidfowl
Copy link
Member

Also, kind of concerning that this was not caught earlier. I guess this test doesn't really run anywhere in an automated way?

This is what we're working on 😄.

@davidfowl
Copy link
Member

My take is that the new behavior is more correct, and that we should just adjust the test to have:

This sounds about right.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-app-model Issues pertaining to the APIs in Aspire.Hosting, e.g. DistributedApplication community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Proxyless endpoint does not default the TargetPort when using the callback ctor
4 participants