Skip to content
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

GenericKubernetesApi Patch<T> does not work #971

Closed
kibernetik542 opened this issue Aug 4, 2022 · 6 comments
Closed

GenericKubernetesApi Patch<T> does not work #971

kibernetik542 opened this issue Aug 4, 2022 · 6 comments

Comments

@kibernetik542
Copy link
Contributor

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)
@tg123
Copy link
Member

tg123 commented Aug 4, 2022

linked #846
i will take a look

@brendandburns
Copy link
Contributor

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
Copy link
Contributor

brendandburns commented Aug 8, 2022

Also possible that the Content-type is wrong.

kubernetes-client/python#866

@kibernetik542
Copy link
Contributor Author

I am using 1.22.5 and patching works with manual kubectl

@austin-space
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants