-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Upgrade to KubeClient v3 and log failed Kubernetes API requests #2266
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
Conversation
KubeClient v3 should simplify dependency-management, from Ocelot's perspective: * KubeClient no longer has an external dependency (HTTPlease) for its HttpClient support. The internalised version of this support is now located in the KubeClient.Http namespace. * KubeClient v3 is multi-targeted for net9.0, as well as a couple of older versions that some consumers are still using (support for these older versions will be tailed off over the next couple of minor releases) Related discussion at: tintoy/dotnet-kube-client#166 tintoy/dotnet-kube-client#167
…it isn't going to be used
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adam,
Thanks for opening this PR!
Overall, it is satisfactory, but the logging could be improved.
Another concern is the absence of tests, despite the fact that the current tests are passing.
P.S.
I plan to include it in the current .NET 9 release, so we need to merge this PR within a few days.
: null; | ||
if (!response.IsSuccessStatusCode) | ||
{ | ||
if (_logger.IsEnabled(LogLevel.Debug)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not certain, but if we use the native Ocelot logger, then all Log*
methods have internal check to determine whether logging is enabled. Therefore, this if
clause may be redundant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, ILogger does the same, but this check was more to decide if we want to check whether to try deserialising the error response; it’s a pattern I tend to use when we perform some non-zero-cost operation to collect info purely for logging purposes. Some rationale from the runtime folks here:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having said that, as designed, this method swallows any error and returns null (logging being the only place errors are surfaced) so perhaps a warning is more appropriate? just didn’t want to fill up the log with noise… 🤷🏻
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've moved that logic out of EndPointClientV1
, to maintain separation of concerns; it now lives in the caller (Kube
).
@@ -25,8 +25,8 @@ | |||
<NoWarn>1591</NoWarn> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="KubeClient" Version="2.5.12" /> | |||
<PackageReference Include="KubeClient.Extensions.DependencyInjection" Version="2.5.12" /> | |||
<PackageReference Include="KubeClient" Version="3.0.0" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, it should be 3.0.1 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, fair call - I'd only just published that; will pull in the new version 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm - just before I push this change, I thought I'd better check - KubeClient
3.0.1
requires Microsoft.Extensions.*
9.0.3
(Ocelot's test projects currently use 9.0.1
; tried upgrading, and all are tests still passing, but it's your call if you want me to upgrade).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please go ahead and upgrade. Anyway, before the release I'll upgrade all packs
Yes, I think I can probably whip up a couple of integration tests for this, if nothing else (KubeClient has a testability framework that can be used to mock out the Kubernetes API for tests using a custom For example: https://github.com/tintoy/dotnet-kube-client/blob/ee1b9d29ff65b212b3b6c2da47fce1e7ebe3abb4/test/KubeClient.Tests/ErrorHandling/ExceptionTests.cs#L39 I’ll try to get the tests done sometime today, if I can (it’s Sunday here, and next week is already starting to look pretty heavy). |
…and into its caller
private Task<EndpointsV1> GetEndpoint() => _kubeApi | ||
.ResourceClient<IEndPointClient>(client => new EndPointClientV1(client)) | ||
.GetAsync(_configuration.KeyOfServiceInK8s, _configuration.KubeNamespace); | ||
private async Task<EndpointsV1> GetEndpoint() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've moved this logic here because it keeps the resource-client implementation cleaner (since it wouldn't otherwise be clear to someone who's not seen this code before what the lifetime of the resource client is, vs the lifetime of the containing type or its logger).
@raman-m I've reworked the logic a bit (see comments on the commit). Can you let me know if you're ok with those changes? If so, I can get started on the tests. |
Regarding the tests - although there are existing tests for the Kubernetes provider, and I can see how to extend them to test handling of error responses, I'm not confident I can test the logging behaviour without risking reinventing the wheel (I see a couple of of internal-only/test-specific implementations of |
Ah, good - I see there's already a framework for serving up a fake Kubernetes API; will use that, instead. |
…I used by service-discovery tests
Please proceed. It is to upgrade the tests in the unit testing project: Kubernetes.
Please update unit tests only. There is no need to rewrite or refactor acceptance tests. They should be solid, meaning they require minimal updating if they fail. Therefore, you need to test all new implementations with unit tests.
Indeed, we utilize |
Adam FYI, you probably saw PR #2257 and commit 4b6b96a |
Just to confirm - by this, do you mean unit tests verifying the underlying implementation (using Moq or similar) or do you mean unit tests for the behaviour changes resulting from the implementation change? |
…netes API used by service-discovery tests" This reverts commit 9a8bf9c.
Never mind - I see the tests you're referring to; I'll extend those. |
string logMessage = messageFactory(); | ||
logMessage.ShouldNotBeNullOrWhiteSpace(); | ||
|
||
// This is a little fragile, as it may change if other entries are logged due to implementation changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@raman-m small issue, as noted in these comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow!... 😮
I don't understand why it is difficult to test. Can't we set up the mocker accordingly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem (as it looks to me) is that the test can't know for sure what other components may log messages as well (in this case, the retry facility uses the same logger and trying to verify those logged messages would make the whole thing too fragile by making this unit test coupled to the implementation of other components such as the retry).
I've always aimed to make unit tests, in particular, to test behaviour without being coupled to the implementation; otherwise the tests may have to be changed each time the implementation changes which removes one of the (in my opinion) best benefits of unit testing.
But I'm not that familiar with the code-base and so I'm open to changing it if you believe that would be better 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, the issue lies in the retry logic of the upper context, correct? It seems we have been debating this extensively. If the problem truly exists, I will identify it in the next round of refactoring the logic. For now, we can omit this.
No worries, happy to discuss / fill in details if required. Potentially useful KubeClient docs for registering |
@tintoy commented on March 17
No, I meant: How will your changes be reflected in the current K8s doc for the development version? Please note that the development version is still unreleased. Are these documents relevant? Please review them. P. S. Updating the documentation will be the final step. For now, I will conduct the final code review today by loading the solution into Visual Studio. |
Oh - sure, will do. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the development is complete. The final step is review the documentation.
…ce it only has a single await as the last statement (return await)
Regarding the documentation, it looks to me like no changes are required as a result of this PR's changes. Later, however, it might be worth adding some information to the docs about KubeClient's support for: For example, the code from step 2: Action<KubeClientOptions> configureKubeClient = opts =>
{
opts.ApiEndPoint = new UriBuilder("https", "my-host", 443).Uri;
opts.AccessToken = "my-token";
opts.AuthStrategy = KubeAuthStrategy.BearerToken;
opts.AllowInsecure = true;
};
builder.Services
.AddOptions<KubeClientOptions>()
.Configure(configureKubeClient); // manual binding options via IOptions<KubeClientOptions> Could also be written like this: services.AddKubeClientOptions(clientOptions =>
{
clientOptions.ApiEndPoint = new UriBuilder("https", "my-host", 443).Uri;
clientOptions.AuthStrategy = KubeAuthStrategy.BearerToken;
clientOptions.AccessToken = "my-token";
clientOptions.AllowInsecure = true;
}); |
@tintoy commented on March 18
Great! If no changes needed when upgrading to v3 version then I have a plan to release current docs with this extra method:
Good suggestion. However, the Ocelot documentation recommends adding Kubernetes support using the native Ocelot Switching to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ready for delivery ✔️
@tintoy Congrats! 🎉
KubeClient v3 should simplify dependency-management, from Ocelot's perspective:
KubeClient.Http
namespace.net9.0
, as well as a couple of older versions that some consumers are still using (support for these older versions will be tailed off over the next couple of minor releases)Related discussion at:
tintoy/dotnet-kube-client#166
tintoy/dotnet-kube-client#167
CC: @raman-m (as previously discussed; sorry for the extended delay!)
Proposed Changes
KubeClient
packages tov3.0.0