csharp
csharp copied to clipboard
GenericKubernetesApi Patch<T> does not work
As there is no patch method on old GenericClient, I used patch with new GenericKuberenetesApi but it fails. P.S. all -- Read, List, Delete, Create -- works fine
my code looks like:
public async Task<bool> CreateHelmRelease(string kubeConfig, string targetNamespace, string projectAppName, string
repoName, string catalogAppName, JsonNode values, string version,bool isUpgrade, CancellationToken cancellationToken)
{
try
{
var (client, _) = BaseKubernetesClient(kubeConfig);
var generic = new GenericKubernetesApi(CommonApplicationConstants.HelmFluxApiGroup, CommonApplicationConstants.FluxApiVersion2, CommonApplicationConstants.HelmReleasePluralName, client);
var namespaces = await client.ListNamespaceAsync(cancellationToken: cancellationToken);
var requestedNamespace = namespaces.Items.FirstOrDefault(x => x.Metadata.Name == targetNamespace);
// Check target namespace exists
if (requestedNamespace == null)
{
await client.CreateNamespaceAsync(new V1Namespace
{
Metadata = new V1ObjectMeta
{
Name = targetNamespace
}
}, cancellationToken: cancellationToken);
Thread.Sleep(1000);
}
var obj = new HelmObject
{
ApiVersion = $"{CommonApplicationConstants.HelmFluxApiGroup}/{CommonApplicationConstants.FluxApiVersion2}",
Kind = "HelmRelease",
Metadata = new V1ObjectMeta
{
Name = $"{projectAppName}-{targetNamespace}",
NamespaceProperty = CommonKubernetesConstants.AppsNamespace
},
Spec = new HelmSpec
{
Interval = "5m",
TargetNamespace = targetNamespace,
StorageNamespace = targetNamespace,
ReleaseName = projectAppName,
Chart = new Chart
{
Spec = new ChartSpec
{
Chart = catalogAppName,
Version = version,
SourceRef = new SourceRef
{
Kind = "HelmRepository",
Name = repoName
},
Interval = "1m"
}
},
Values = values
}
};
switch (isUpgrade)
{
case true:
await generic.PatchAsync<HelmObject>(CommonKubernetesConstants.AppsNamespace,$"{projectAppName}-{targetNamespace}",obj,cancellationToken);
break;
default:
await generic.CreateAsync(obj, cancellationToken);
break;
}
return true;
}
catch (Exception e)
{
_logger.LogError(e.Message);
return false;
}
}
And error I am getting :
k8s.Autorest.HttpOperationException: Operation returned an invalid status code 'UnsupportedMediaType'
at k8s.Kubernetes.SendRequestRaw(String requestContent, HttpRequestMessage httpRequest, CancellationToken cancellationToken)
at k8s.AbstractKubernetes.k8s.ICustomObjectsOperations.PatchNamespacedCustomObjectWithHttpMessagesAsync(Object body, String group, String version, String namespaceParameter, String plural, String name, String dryRun, String fieldManager, Nullable`1 force, IReadOnlyDictionary`2 customHeaders, CancellationToken cancellationToken)
at k8s.Util.Common.Generic.GenericKubernetesApi.PatchAsync[T](String namespaceProperty, String name, Object obj, PatchOptions patchOptions, CancellationToken cancellationToken)
linked #846 i will take a look
This may be happening b/c it is trying to do server-side apply on a version of Kubernetes that doesn't support it.
https://stackoverflow.com/questions/63625000/terraform-kubernetes-alpha-provider-fails-with-415-unsupported-media-type
Also possible that the Content-type is wrong.
https://github.com/kubernetes-client/python/issues/866
I am using 1.22.5 and patching works with manual kubectl
I can help a bit here as I was running into this exact problem.
For debugging this case: you should probably catch the k8s.Autorest.HttpOperationException
and read out the response content. Something like this:
try
{
// Make your request
}
catch(HttpOperationException ex)
{
Console.WriteLine(ex.Response.Content);
}
That should at least give you a good hint about what's going wrong.
I would bet that you're getting an error about not being able to use force
if you're not running a server side apply(as I got). This is a bug here where the strings end up defaulting to null, but the boolean force property, as a non-nullable value type, ends up defaulting to false. This means that when we try to add query parameters to the request, the strings get dropped, but force=false
is still included, causing the request to fail.
I would say that this is a straightforward fix to just make force
nullable in PatchOptions
and call it a day, but it seems that GenericKubernetesApi
has been removed from the published package in favor of GenericClient
, which doesn't even have a patch method on it. Seems like the only option right now is to use Kubernetes.PatchNamespacedCustomObjectWithHttpMessagesAsync
or Kubernetes.PatchClusterCustomObjectWithHttpMessagesAsync
until #846 is properly addressed.