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

CoreV1API_listPodForAllNamespaces/CoreV1API_listNamespacedPod API return 422 error #209

Closed
KagumiRA opened this issue Oct 26, 2023 · 19 comments · Fixed by #210
Closed

CoreV1API_listPodForAllNamespaces/CoreV1API_listNamespacedPod API return 422 error #209

KagumiRA opened this issue Oct 26, 2023 · 19 comments · Fixed by #210

Comments

@KagumiRA
Copy link

Hello, I have problem when I try to run c/examples/list_pod/main.c , the program return
The return code of HTTP request=422
Cannot get any pod.
My k8s client version is "v1.28.2" and server version is "v1.28.2". Please help me debug these problems!

@brendandburns
Copy link
Contributor

422 means that the body of the request is malformed.

My guess is that your cluster doesn't have a default namespace, but that's a guess.

You should print the body of the response and you will get a more detailed error message.

@KagumiRA
Copy link
Author

422 means that the body of the request is malformed.

My guess is that your cluster doesn't have a default namespace, but that's a guess.

You should print the body of the response and you will get a more detailed error message.

Thanks for helping me!! I try running the code under my cluster having default namespace and return same error. How can I print the body of the response? Where do the response exist?

@Hgary
Copy link

Hgary commented Oct 27, 2023

it works using python, but when i use c language, i have the same error. i just change the namespace to my namespace.
pod_list = CoreV1API_listNamespacedPod(apiClient, "dialogue-dev",
NULL, /* pretty /
0, /
allowWatchBookmarks /
NULL, /
continue /
NULL, /
fieldSelector /
NULL, /
labelSelector /
0, /
limit /
NULL, /
resourceVersion /
NULL, /
resourceVersionMatch /
0, /
sendInitialEvents /
0, /
timeoutSeconds /
0 /
watch */
);

@Hgary
Copy link

Hgary commented Oct 27, 2023

i only get the response_code 422, No additional information。

@ityuhui
Copy link
Member

ityuhui commented Oct 27, 2023

I can reproduce this issue.
Actually this problem also exists in GitHub Action, but we don't parse the return value 422 as an error.
The cause may be some integer type parameters. I'll check it out.

Maybe it helps:
#203

@ityuhui
Copy link
Member

ityuhui commented Oct 27, 2023

(gdb) p (char *)apiClient->dataReceived
$3 = 0x5555555b0250 "{\"kind\":\"Status\",\"apiVersion\":\"v1\",\"metadata\":{},\"status\":\"Failure\",\"message\":\"ListOptions.meta.k8s.io \\\"\\\" is invalid: sendInitialEvents: Forbidden: sendInitialEvents is forbidden for list\",\"reason\":\"Invalid\",\"details\":{\"group\":\"meta.k8s.io\",\"kind\":\"ListOptions\",\"causes\":[{\"reason\":\"FieldValueForbidden\",\"message\":\"Forbidden: sendInitialEvents is forbidden for list\",\"field\":\"sendInitialEvents\"}]},\"code\":422}\n"

The parameter sendInitialEvents cannot be passed in the function CoreV1API_listNamespacedPod whether set to 0 or 1.

So this issue cannot be fixed due to the current implementation of the C client.

If you want a workaround, please patch the code:

diff --git a/kubernetes/api/CoreV1API.c b/kubernetes/api/CoreV1API.c
index 53cb60a..ddd2fcd 100644
--- a/kubernetes/api/CoreV1API.c
+++ b/kubernetes/api/CoreV1API.c
@@ -22381,7 +22381,7 @@ CoreV1API_listNamespacedPod(apiClient_t *apiClient, char * _namespace , char * p
     char *keyQuery_sendInitialEvents = NULL;
     char * valueQuery_sendInitialEvents = NULL;
     keyValuePair_t *keyPairQuery_sendInitialEvents = 0;
-    if (1) // Always send boolean parameters to the API server
+    if (0) // Always ignore sendInitialEvents
     {
         keyQuery_sendInitialEvents = strdup("sendInitialEvents");
         valueQuery_sendInitialEvents = calloc(1,MAX_NUMBER_LENGTH);

@KagumiRA
Copy link
Author

KagumiRA commented Oct 28, 2023

Thanks for helping me. I try to ignore sendInitialEvents, but it still returns 422. I try to print the apiClient->dataReceived in gdb, but it has nothing.

(gdb) p (char *)apiClient->dataReceived 
$1 = 0x0

@ityuhui
Copy link
Member

ityuhui commented Oct 28, 2023

You have to add a breakpoint at this line:

b CoreV1API.c:22442

to debug the C client library and then print apiClient->dataReceived

https://github.com/kubernetes-client/c/blob/b02e6e5d5865f822d0b19a9be2c306897ae761c1/kubernetes/api/CoreV1API.c#L22442

@Hgary
Copy link

Hgary commented Oct 30, 2023

i ignore sendInitialEvents, it works. thanks for help from ityuhui .

error:
Breakpoint 2, CoreV1API_listNamespacedPod (apiClient=0x555555586390, _namespace=0x555555556008 "dialogue-dev", pretty=0x0, allowWatchBookmarks=0, _continue=0x0, fieldSelector=0x0, labelSelector=0x0, limit=0, resourceVersion=0x0,
resourceVersionMatch=0x0, sendInitialEvents=0, timeoutSeconds=0, watch=0) at /root/k8s-study/c/kubernetes/api/CoreV1API.c:22442
22442 cJSON *CoreV1APIlocalVarJSON = cJSON_Parse(apiClient->dataReceived);
(gdb) n
22443 v1_pod_list_t *elementToReturn = v1_pod_list_parseFromJSON(CoreV1APIlocalVarJSON);
(gdb) p apiClient
$1 = (apiClient_t *) 0x555555586390
(gdb) p *apiClient
$2 = {basePath = 0x55555558ade0 "https://10.150.148.26:6443", sslConfig = 0x555555588090, dataReceived = 0x5555555b9ae0, dataReceivedLen = 412, data_callback_func = 0x0, progress_func = 0x0, progress_data = 0x0, response_code = 422,
apiKeys_BearerToken = 0x5555555700e0}
(gdb) p apiClient->dataReceived
$3 = (void *) 0x5555555b9ae0
(gdb) p *apiClient->dataReceived
Attempt to dereference a generic pointer.
(gdb) p (char *)apiClient->dataReceived
$4 = 0x5555555b9ae0 "{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"ListOptions.meta.k8s.io \"\" is invalid: sendInitialEvents: Forbidden: sendInitialEvents is forbidden for list","reason":"...
(gdb)

@Hgary
Copy link

Hgary commented Oct 30, 2023

it seems all api need ignore sendInitialEvents(for example, CoreV1API_listNamespacedEndpoints)? Is there an official upgrade to address this issue?

@KagumiRA
Copy link
Author

KagumiRA commented Oct 30, 2023

Thanks for helping!
I try to print apiClient->dataReceived after adding a breakpoint b CoreV1API.c:22442 with ignoring sendInitialEvents in CoreV1API.c:22381 and CoreV1API.c:20988.
I still get the same result:

(gdb) p (char*)apiClient->dataReceived
$2 = 0x555555669f10 "{\"kind\":\"Status\",\"apiVersion\":\"v1\",\"metadata\":{},\"status\":\"Failure\",\"message\":\"ListOptions.meta.k8s.io \\\"\\\" is invalid: sendInitialEvents: Forbidden: sendInitialEvents is forbidden for list\",\"reason\":\"Invalid\",\"details\":{\"group\":\"meta.k8s.io\",\"kind\":\"ListOptions\",\"causes\":[{\"reason\":\"FieldValueForbidden\",\"message\":\"Forbidden: sendInitialEvents is forbidden for list\",\"field\":\"sendInitialEvents\"}]},\"code\":422}\n"

At least, we know what problem lead to return 422 in my environment. How can I fix the problem? Thanks!

@ityuhui
Copy link
Member

ityuhui commented Oct 31, 2023

This problem (whether to send int/boolean type parameters to the API server when their value is 0) has been around for a while and we need to find a solution to fix it.

I have some ideas:

Option 1: Add a flag sendXxx for every int/boolean type parameter xxx to control whether to send xxx to the API server.

e.g.

v1_pod_list_t* CoreV1API_listPodForAllNamespaces(apiClient_t *apiClient, 
                    int sendAllowWatchBookmarks, int allowWatchBookmarks, 
                    char * _continue, char * fieldSelector, char * labelSelector, 
                    int sendLimit, int limit, 
                    char * pretty,  char * resourceVersion, char * resourceVersionMatch, 
                    int sendSendInitialEvents, int sendInitialEvents, 
                    int sendTimeoutSeconds, int timeoutSeconds, 
                    int sendWatch, int watch);

Option 2: Use int *foo for the int/boolean type parameters, if foo == NULL, ignore sending.

e.g.

v1_pod_list_t* CoreV1API_listPodForAllNamespaces(apiClient_t *apiClient,
                    int *pAllowWatchBookmarks, 
                    char * _continue, char * fieldSelector, char * labelSelector, 
                    int *pLimit, 
                    char * pretty, char * resourceVersion, char * resourceVersionMatch, 
                    int *pSendInitialEvents, 
                    int *pTimeoutSeconds, 
                    int *pWatch);

Option 3: Add a parameter alwaysSendIntParameter in apiClient_t

if (apiClilent->alwaysSendIntParameter) {
    always send int/boolean type parameters
} else {
    send the int/boolean type parameters whose value is not `NULL/0`
}

Users need to set apiClilent->alwaysSendIntParameter before calling the API such as CoreV1API_listPodForAllNamespaces

Hi @brendandburns
What do you think of these solutions ?

cc @wing328 @zhemant @michelealbano for early discussion as this change will eventually be made in OpenAPI-Generator/c-libcurl.

@brendandburns
Copy link
Contributor

I would vote for either

typedef struct {
   bool is_none,
   int value
} optional_int_t;

or using int* with NULL meaning "don't send"

int* is probably easier for clients to deal with the change.

@ityuhui
Copy link
Member

ityuhui commented Nov 8, 2023

I prefer int* to solve this issue.
What do you think ? @wing328 @zhemant @michelealbano

@zhemant
Copy link

zhemant commented Nov 8, 2023

I would say int * and possibly similar for boolean/any other primitive which is not pointer. Then it is also easy to handle from code generator as it will possibly remove the need of individual type separation

@wing328
Copy link

wing328 commented Nov 8, 2023

I prefer int* to solve this issue.

Me too.

@michelealbano
Copy link

michelealbano commented Nov 8, 2023 via email

@ityuhui
Copy link
Member

ityuhui commented Nov 10, 2023

Thank you for your votes and suggestions !Based on the result of discussion, I'm going to implement the int* solution.

So far, we have been discussing the case in the API function parameter list, but in fact the same problem exists with OpenAPI's model. The detail is in #193

In short, the int/boolean members/fields in a model should also be changed to int* to support the required check:

https://github.com/kubernetes-client/c/blob/b02e6e5d5865f822d0b19a9be2c306897ae761c1/kubernetes/model/v1_daemon_set_status.c#L112C22-L112C22

I'll make this the next phase of work once I resolve this issue.

@brendandburns
Copy link
Contributor

I also prefer using int*. I am a little worried for all the heap fragmentation it will cause, but it's still the best option. Michele

On Wed, Nov 8, 2023 at 3:26 PM William Cheng @.> wrote: I prefer int to solve this issue. Me too. — Reply to this email directly, view it on GitHub <#209 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AC66LHCC5B6N6XU32P2YM6LYDOI7TAVCNFSM6AAAAAA6QQ25POVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQMBRHE4TKMRZGU . You are receiving this because you were mentioned.Message ID: @.*>

fwiw, it doesn't have to cause heap fragementation if people use & to pass pointers to stack allocated variables when they make the client calls.

e.g.

int foo;
someApiCall(&foo);

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

Successfully merging a pull request may close this issue.

7 participants