AoT version with AKS `kubelogin` throws exception on creating configuration
Describe the bug
Using KubernetesClient.Aot throws an exception when trying to create a configuration via KubernetesClientConfiguration.BuildConfigFromConfigFile() that utilizes AKS kubelogin.
Exception is
k8s.Exceptions.KubeConfigException: 'external exec failed due to uncaught exception: System.ArgumentNullException: Value cannot be null. (Parameter 'jsonTypeInfo')
at System.Text.Json.ThrowHelper.ThrowArgumentNullException(String parameterName)
at System.Text.Json.JsonSerializer.Deserialize(String json, JsonTypeInfo jsonTypeInfo)
at k8s.KubernetesJson.Deserialize[TValue](String json, JsonSerializerOptions jsonSerializerOptions)
at k8s.KubernetesClientConfiguration.ExecuteExternalCommand(ExternalExecution config)'
Kubernetes C# SDK Client Version 15.0.1
Server Kubernetes Version 1.30.6
Dotnet Runtime Version .NET 9
To Reproduce
- Use kubelogin example as a reference
- First, confirm that regular
KubernetesClientversion 15.0.1 works correct when callingKubernetesClientConfiguration.BuildConfigFromConfigFile() - Now change the package to
KubernetesClient.Aotversion 15.0.1 and try again - get an exception
Expected behavior Configuration should be created successfully.
KubeConfig
Please refer to the linked sample but here's relevant users section from my config specifically:
users:
- name: clusterUser_<name>
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
args:
- get-token
- --environment
- AzurePublicCloud
- --server-id
- <server_id>
- --client-id
- <client_id>
- --tenant-id
- <tenant_id>
- --login
- devicecode
command: kubelogin
env: null
installHint: |2
kubelogin is not installed which is required to connect to AAD enabled cluster.
To learn more, please go to https://aka.ms/aks/kubelogin
interactiveMode: IfAvailable
provideClusterInfo: false
Where do you run your app with Kubernetes SDK:
- OS: Windows 11 Pro
- Environment: Launching project with debug in Visual Studio
Additional context
I guess it could be related to this one as well: https://github.com/kubernetes-client/csharp/issues/1598
yup this is something dynamic, so not fully supported in aot
This should be fixable with a PR by setting the jsonTypeInfo on https://github.com/kubernetes-client/csharp/blob/61e6b13fd7828eb3d76b249b259b3444b0462564/src/KubernetesClient.Aot/KubernetesClientConfiguration.ConfigFile.cs#L515
[JsonSerializable(typeof(ExecCredentialResponse))]
internal partial class ExecCredentialResponseContext : JsonSerializerContext
{
}
This should be fixable with a PR by setting the jsonTypeInfo on
csharp/src/KubernetesClient.Aot/KubernetesClientConfiguration.ConfigFile.cs
Line 515 in 61e6b13
var responseObject = KubernetesJson.Deserialize<ExecCredentialResponse>(process.StandardOutput.ReadToEnd());
[JsonSerializable(typeof(ExecCredentialResponse))] internal partial class ExecCredentialResponseContext : JsonSerializerContext { }
The code dynamically looks up the JsonTypeInfo required in the AOT version of the deserialize method:
public static TValue Deserialize<TValue>(string json, JsonSerializerOptions jsonSerializerOptions = null)
{
var info = SourceGenerationContext.Default.GetTypeInfo(typeof(TValue));
return (TValue)JsonSerializer.Deserialize(json, info);
}
#1616 should fix it, but I have not yet had a chance to test to verify that it fixes the exact problem that led me to this issue, nor have I had a chance to set up a test environment to run the unit tests. There is also the matter of how the project has multiple source generators operating on the same classes and while this is apparently working here, this is generally not supported, so I may be missing some nuances.
More generally, the JsonTypeInfo should probably be used for both the .Aot and non-.Aot versions of the client library (where possible, of course, and in such a way that the non-.Aot version can fall back to dynamic serialization code). Using the source generated JSON serializer that way would result in build-time errors instead of runtime errors whenever someone gets around to calling an impacted method. Such an approach would also provide a way to use CRDs with the .Aot version (and provide same the build vs runtime benefits). This does mean finding some way to do so for runtimes that support it, without making a mess of the templates/generated code for runtimes that do not.
What are the benefits of a user-configurable JsonSerializerOptions other than for interoperability with a (hopefully hypothetical) variant of Kubernetes that uses nearly the same API, but with incompatible JSON formatting? Many libraries and much sample code make JSON serialization configurable, but in this case a specific API with specific requirements is being targeted.
By similar arguments, regular expressions should probably be source generated as well. Beyond build-time error detection and reduced startup costs, this would also benefit performance on the .Aot version since the native runtime cannot do dynamically compilation.
In case anyone else is running into problems generating .sln files, it appears to be broken with version 12.0.3 of Microsoft.VisualStudio.SlnGen . Updating to 12.0.10 got it working for me.
TL;DR: source generation should be used where practical for both the .Aot and non-.Aot versions of the library.
The Kubernetes project currently lacks enough contributors to adequately respond to all issues.
This bot triages un-triaged issues according to the following rules:
- After 90d of inactivity,
lifecycle/staleis applied - After 30d of inactivity since
lifecycle/stalewas applied,lifecycle/rottenis applied - After 30d of inactivity since
lifecycle/rottenwas applied, the issue is closed
You can:
- Mark this issue as fresh with
/remove-lifecycle stale - Close this issue with
/close - Offer to help out with Issue Triage
Please send feedback to sig-contributor-experience at kubernetes/community.
/lifecycle stale
The Kubernetes project currently lacks enough active contributors to adequately respond to all issues.
This bot triages un-triaged issues according to the following rules:
- After 90d of inactivity,
lifecycle/staleis applied - After 30d of inactivity since
lifecycle/stalewas applied,lifecycle/rottenis applied - After 30d of inactivity since
lifecycle/rottenwas applied, the issue is closed
You can:
- Mark this issue as fresh with
/remove-lifecycle rotten - Close this issue with
/close - Offer to help out with Issue Triage
Please send feedback to sig-contributor-experience at kubernetes/community.
/lifecycle rotten
The Kubernetes project currently lacks enough active contributors to adequately respond to all issues and PRs.
This bot triages issues according to the following rules:
- After 90d of inactivity,
lifecycle/staleis applied - After 30d of inactivity since
lifecycle/stalewas applied,lifecycle/rottenis applied - After 30d of inactivity since
lifecycle/rottenwas applied, the issue is closed
You can:
- Reopen this issue with
/reopen - Mark this issue as fresh with
/remove-lifecycle rotten - Offer to help out with Issue Triage
Please send feedback to sig-contributor-experience at kubernetes/community.
/close not-planned
@k8s-triage-robot: Closing this issue, marking it as "Not Planned".
In response to this:
The Kubernetes project currently lacks enough active contributors to adequately respond to all issues and PRs.
This bot triages issues according to the following rules:
- After 90d of inactivity,
lifecycle/staleis applied- After 30d of inactivity since
lifecycle/stalewas applied,lifecycle/rottenis applied- After 30d of inactivity since
lifecycle/rottenwas applied, the issue is closedYou can:
- Reopen this issue with
/reopen- Mark this issue as fresh with
/remove-lifecycle rotten- Offer to help out with Issue Triage
Please send feedback to sig-contributor-experience at kubernetes/community.
/close not-planned
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.
/reopen This issue still exists