kubernetes-client / c

Official C client library for Kubernetes
Apache License 2.0
141 stars 45 forks source link

v1_pod_list_parseFromJSON does not parse pod statuses #221

Closed homer6 closed 4 months ago

homer6 commented 4 months ago

Just curious why the status is not being parsed for namespaced pod listings (CoreV1API_listNamespacedPod).

Is this an intentional omission?

homer6 commented 4 months ago

I changed the implementation of CoreV1API_listNamespacedPod to print the raw response. The statuses are in the payload, they just not being parsed.

    if( apiClient->dataReceived ){
        printf("%s\n",(char*)apiClient->dataReceived);
    }
ityuhui commented 4 months ago

Can you print your raw response of CoreV1API_listNamespacedPod here ?

homer6 commented 4 months ago

Response payload:

{"kind":"PodList","apiVersion":"v1","metadata":{"resourceVersion":"107202"},"items":[{"metadata":{"name":"nginx","namespace":"default","uid":"03d1ab78-dfa9-47cb-acdc-9f9ee3a1acb7","resourceVersion":"62595","creationTimestamp":"2024-02-26T01:52:24Z","managedFields":[{"manager":"unknown","operation":"Update","apiVersion":"v1","time":"2024-02-26T01:52:24Z","fieldsType":"FieldsV1","fieldsV1":{"f:spec":{"f:containers":{"k:{\"name\":\"nginx\"}":{".":{},"f:image":{},"f:imagePullPolicy":{},"f:name":{},"f:ports":{".":{},"k:{\"containerPort\":80,\"protocol\":\"TCP\"}":{".":{},"f:containerPort":{},"f:protocol":{}}},"f:resources":{},"f:terminationMessagePath":{},"f:terminationMessagePolicy":{}}},"f:dnsPolicy":{},"f:enableServiceLinks":{},"f:restartPolicy":{},"f:schedulerName":{},"f:securityContext":{},"f:terminationGracePeriodSeconds":{}}}},{"manager":"k3s","operation":"Update","apiVersion":"v1","time":"2024-02-26T01:52:26Z","fieldsType":"FieldsV1","fieldsV1":{"f:status":{"f:conditions":{"k:{\"type\":\"ContainersReady\"}":{".":{},"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Initialized\"}":{".":{},"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Ready\"}":{".":{},"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:status":{},"f:type":{}}},"f:containerStatuses":{},"f:hostIP":{},"f:phase":{},"f:podIP":{},"f:podIPs":{".":{},"k:{\"ip\":\"10.42.0.30\"}":{".":{},"f:ip":{}}},"f:startTime":{}}},"subresource":"status"}]},"spec":{"volumes":[{"name":"kube-api-access-r4sr2","projected":{"sources":[{"serviceAccountToken":{"expirationSeconds":3607,"path":"token"}},{"configMap":{"name":"kube-root-ca.crt","items":[{"key":"ca.crt","path":"ca.crt"}]}},{"downwardAPI":{"items":[{"path":"namespace","fieldRef":{"apiVersion":"v1","fieldPath":"metadata.namespace"}}]}}],"defaultMode":420}}],"containers":[{"name":"nginx","image":"nginx:1.14.2","ports":[{"containerPort":80,"protocol":"TCP"}],"resources":{},"volumeMounts":[{"name":"kube-api-access-r4sr2","readOnly":true,"mountPath":"/var/run/secrets/kubernetes.io/serviceaccount"}],"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File","imagePullPolicy":"IfNotPresent"}],"restartPolicy":"Always","terminationGracePeriodSeconds":30,"dnsPolicy":"ClusterFirst","serviceAccountName":"default","serviceAccount":"default","nodeName":"wiggum","securityContext":{},"schedulerName":"default-scheduler","tolerations":[{"key":"node.kubernetes.io/not-ready","operator":"Exists","effect":"NoExecute","tolerationSeconds":300},{"key":"node.kubernetes.io/unreachable","operator":"Exists","effect":"NoExecute","tolerationSeconds":300}],"priority":0,"enableServiceLinks":true,"preemptionPolicy":"PreemptLowerPriority"},"status":{"phase":"Running","conditions":[{"type":"Initialized","status":"True","lastProbeTime":null,"lastTransitionTime":"2024-02-26T01:52:24Z"},{"type":"Ready","status":"True","lastProbeTime":null,"lastTransitionTime":"2024-02-26T01:52:26Z"},{"type":"ContainersReady","status":"True","lastProbeTime":null,"lastTransitionTime":"2024-02-26T01:52:26Z"},{"type":"PodScheduled","status":"True","lastProbeTime":null,"lastTransitionTime":"2024-02-26T01:52:24Z"}],"hostIP":"10.0.0.157","podIP":"10.42.0.30","podIPs":[{"ip":"10.42.0.30"}],"startTime":"2024-02-26T01:52:24Z","containerStatuses":[{"name":"nginx","state":{"running":{"startedAt":"2024-02-26T01:52:25Z"}},"lastState":{},"ready":true,"restartCount":0,"image":"docker.io/library/nginx:1.14.2","imageID":"docker.io/library/nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d","containerID":"containerd://1426df14fd18d7d39f595c15cf6bf18e84f0f2d6a701351511e6b3af9bd2a58c","started":true}],"qosClass":"BestEffort"}}]}

Parsed response (null status):

[
    {
        "apiVersion": "v1",
        "kind": "Pod",
        "metadata": {
            "creationTimestamp": "2024-02-26T01:52:24Z",
            "managedFields": [
                {
                    "apiVersion": "v1",
                    "fieldsType": "FieldsV1",
                    "fieldsV1": {
                        "f:spec": {
                            "f:containers": {
                                "k:{\"name\":\"nginx\"}": {
                                    ".": {},
                                    "f:image": {},
                                    "f:imagePullPolicy": {},
                                    "f:name": {},
                                    "f:ports": {
                                        ".": {},
                                        "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": {
                                            ".": {},
                                            "f:containerPort": {},
                                            "f:protocol": {}
                                        }
                                    },
                                    "f:resources": {},
                                    "f:terminationMessagePath": {},
                                    "f:terminationMessagePolicy": {}
                                }
                            },
                            "f:dnsPolicy": {},
                            "f:enableServiceLinks": {},
                            "f:restartPolicy": {},
                            "f:schedulerName": {},
                            "f:securityContext": {},
                            "f:terminationGracePeriodSeconds": {}
                        }
                    },
                    "manager": "unknown",
                    "operation": "Update",
                    "time": "2024-02-26T01:52:24Z"
                },
                {
                    "apiVersion": "v1",
                    "fieldsType": "FieldsV1",
                    "fieldsV1": {
                        "f:status": {
                            "f:conditions": {
                                "k:{\"type\":\"ContainersReady\"}": {
                                    ".": {},
                                    "f:lastProbeTime": {},
                                    "f:lastTransitionTime": {},
                                    "f:status": {},
                                    "f:type": {}
                                },
                                "k:{\"type\":\"Initialized\"}": {
                                    ".": {},
                                    "f:lastProbeTime": {},
                                    "f:lastTransitionTime": {},
                                    "f:status": {},
                                    "f:type": {}
                                },
                                "k:{\"type\":\"Ready\"}": {
                                    ".": {},
                                    "f:lastProbeTime": {},
                                    "f:lastTransitionTime": {},
                                    "f:status": {},
                                    "f:type": {}
                                }
                            },
                            "f:containerStatuses": {},
                            "f:hostIP": {},
                            "f:phase": {},
                            "f:podIP": {},
                            "f:podIPs": {
                                ".": {},
                                "k:{\"ip\":\"10.42.0.30\"}": {
                                    ".": {},
                                    "f:ip": {}
                                }
                            },
                            "f:startTime": {}
                        }
                    },
                    "manager": "k3s",
                    "operation": "Update",
                    "subresource": "status",
                    "time": "2024-02-26T01:52:26Z"
                }
            ],
            "name": "nginx",
            "namespace": "default",
            "resourceVersion": "62595",
            "uid": "03d1ab78-dfa9-47cb-acdc-9f9ee3a1acb7"
        },
        "spec": {
            "containers": [
                {
                    "image": "nginx:1.14.2",
                    "imagePullPolicy": "IfNotPresent",
                    "name": "nginx",
                    "ports": [
                        {
                            "containerPort": 80,
                            "protocol": "TCP"
                        }
                    ],
                    "resources": {},
                    "terminationMessagePath": "/dev/termination-log",
                    "terminationMessagePolicy": "File",
                    "volumeMounts": [
                        {
                            "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
                            "name": "kube-api-access-r4sr2",
                            "readOnly": true
                        }
                    ]
                }
            ],
            "dnsPolicy": "ClusterFirst",
            "enableServiceLinks": true,
            "nodeName": "wiggum",
            "preemptionPolicy": "PreemptLowerPriority",
            "restartPolicy": "Always",
            "schedulerName": "default-scheduler",
            "securityContext": {},
            "serviceAccount": "default",
            "serviceAccountName": "default",
            "terminationGracePeriodSeconds": 30,
            "tolerations": [
                {
                    "effect": "NoExecute",
                    "key": "node.kubernetes.io/not-ready",
                    "operator": "Exists",
                    "tolerationSeconds": 300
                },
                {
                    "effect": "NoExecute",
                    "key": "node.kubernetes.io/unreachable",
                    "operator": "Exists",
                    "tolerationSeconds": 300
                }
            ],
            "volumes": [
                {
                    "name": "kube-api-access-r4sr2",
                    "projected": {
                        "defaultMode": 420,
                        "sources": [
                            {
                                "serviceAccountToken": {
                                    "expirationSeconds": 3607,
                                    "path": "token"
                                }
                            },
                            {
                                "configMap": {
                                    "items": [
                                        {
                                            "key": "ca.crt",
                                            "path": "ca.crt"
                                        }
                                    ],
                                    "name": "kube-root-ca.crt"
                                }
                            },
                            {
                                "downwardAPI": {
                                    "items": [
                                        {
                                            "fieldRef": {
                                                "apiVersion": "v1",
                                                "fieldPath": "metadata.namespace"
                                            },
                                            "path": "namespace"
                                        }
                                    ]
                                }
                            }
                        ]
                    }
                }
            ]
        },
        "status": null
    }
]
ityuhui commented 4 months ago

I debugged list_pod in my env and it works:

Breakpoint 1, list_pod (apiClient=0x555555589500) at main.c:28
28              printf("\tThe pod name: %s\n", pod->metadata->name);
(gdb) p pod
$1 = (v1_pod_t *) 0x5555555b17e0
(gdb) p *pod
$2 = {api_version = 0x0, kind = 0x0, metadata = 0x5555555a4d80, spec = 0x5555555a9940, status = 0x55555558e910}
(gdb) p *pod->status
$3 = {conditions = 0x5555555a9a70, container_statuses = 0x5555555a9c90, ephemeral_container_statuses = 0x0, host_ip = 0x5555555a9ed0 "172.18.0.2",
  host_ips = 0x0, init_container_statuses = 0x0, message = 0x0, nominated_node_name = 0x0, phase = 0x5555555a9eb0 "Running",
  pod_ip = 0x5555555a9e90 "10.244.0.3", pod_ips = 0x5555555a9dd0, qos_class = 0x5555555a9e70 "BestEffort", reason = 0x0, resize = 0x0,
  resource_claim_statuses = 0x0, start_time = 0x5555555a9e50 "2023-12-14T13:35:39Z"}

Can you debug your binary and find out which parsing function fails ?

homer6 commented 4 months ago

So, it looks like the pod status is there. I was able to reproduce your debug statements.

However, two parsing function appear to be malfunctioning.

image

In reference 1, the status parsing function, that was orginally always returning null.

In reference 2, the pod parsing function, that now shows the status, but some of the entire pods fail entirely (null) from that function. So in a pod list of 10 pods, half of them are full parsed and half of them are completely null.

The reason that I was using the individual v1_object_meta_convertToJSON, v1_pod_spec_convertToJSON, and v1_pod_status_convertToJSON in the first place is because v1_pod_convertToJSON was returning null on about half of the pod records, whereas v1_object_meta_convertToJSON and v1_pod_spec_convertToJSON always work and v1_pod_status_convertToJSON always fails.

I'm attaching the pod_list_output.txt, which contains both the raw (received from the api client; you can tell it's directly from the api client because it's not pretty-printed) and the parsed data from the above code run.

You'll be able to see that I'm pulling all of the pods from each of the namespaces. Notice that some of the pod records are entirely null.

pod_list_output.txt

homer6 commented 4 months ago

As an experiment, I bypassed all of the parsing functions and the result was exactly as I expected. I think there are just a number of implementation issues with the serde, which is not technically required on my end. I just need the raw JSON.

homer6 commented 4 months ago

I adopted the generic API, from @ityuhui's suggestion, and it worked well. https://github.com/kubernetes-client/c/issues/224#issuecomment-1970240528

Thanks @ityuhui