Description
When creating a new client instance by passing in an HttpClient
, a NullReferenceException
is thrown by the InitializeFromConfig
method because the HttpClientHandler
property is null. This can be demonstrated by attempting to run the httpClientFactory sample in the examples
folder.
Full stack trace:
Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
at k8s.Kubernetes.InitializeFromConfig(KubernetesClientConfiguration config) in C:\dev\github\third_party\csharp\src\KubernetesClient\Kubernetes.ConfigInit.cs:line 108
at k8s.Kubernetes..ctor(KubernetesClientConfiguration config, HttpClient httpClient, Boolean disposeHttpClient) in C:\dev\github\third_party\csharp\src\KubernetesClient\Kubernetes.ConfigInit.cs:line 46 at k8s.Kubernetes..ctor(KubernetesClientConfiguration config, HttpClient httpClient) in C:\dev\github\third_party\csharp\src\KubernetesClient\Kubernetes.ConfigInit.cs:line 25
at httpClientFactory.Program.<>c.<Main>b__0_2(HttpClient httpClient, IServiceProvider serviceProvider) in C:\dev\github\third_party\csharp\examples\httpClientFactory\Program.cs:line 31
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitTransient(TransientCallSite transientCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitTransient(TransientCallSite transientCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider) at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)
at httpClientFactory.Program.Main(String[] args) in C:\dev\github\third_party\csharp\examples\httpClientFactory\Program.cs:line 41
at httpClientFactory.Program.<Main>(String[] args)
This is likely related to #307, where it was suggested that a fix to the AutoRest library might be necessary. After digging a bit deeper this afternoon, I think this may be an issue that does need to be worked through in the k8s client code. When using .NET Core's HttpClientFactory
pattern, by the time you get an HttpClient
instance, it's already been initialized with its HttpClientHandler
, and there's no (good) way for AutoRest to get this back out. I believe that's the reason the code linked in #307 for ServiceClient
doesn't already set the HttpClientHandler
property when passed an already existing HttpClient
.
The only two solutions I can think of are to either pass an already-configured HttpClient
into the Kubernetes client constructor and not run the offending pieces of InitializeFromConfig
in that scenario, or pass in both the HttpClient
and whatever HttpClientHandler
was used to create it. The latter feels a bit wonky, so I've worked up a solution that implements the former, since it plays nicer with the HttpClientFactory implementation that .NET Core provides. Once I've had time to vet a few additional scenarios (i.e., testing with frameworks other than .NET Core), I'll submit my changes as a PR for review.