csharp icon indicating copy to clipboard operation
csharp copied to clipboard

GenericKubernetesApi Patch<T> does not work

Open kibernetik542 opened this issue 2 years ago • 5 comments

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)

kibernetik542 avatar Aug 04 '22 11:08 kibernetik542

linked #846 i will take a look

tg123 avatar Aug 04 '22 12:08 tg123

This may be happening b/c it is trying to do server-side apply on a version of Kubernetes that doesn't support it.

brendandburns avatar Aug 08 '22 19:08 brendandburns

https://stackoverflow.com/questions/63625000/terraform-kubernetes-alpha-provider-fails-with-415-unsupported-media-type

brendandburns avatar Aug 08 '22 19:08 brendandburns

Also possible that the Content-type is wrong.

https://github.com/kubernetes-client/python/issues/866

brendandburns avatar Aug 08 '22 19:08 brendandburns

I am using 1.22.5 and patching works with manual kubectl

kibernetik542 avatar Aug 08 '22 19:08 kibernetik542

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.

austin-space avatar Sep 27 '22 23:09 austin-space