From be3b335b9c864aa9dec3ebddfde4e464ce5df645 Mon Sep 17 00:00:00 2001 From: Hui Yu Date: Wed, 9 Sep 2020 17:56:23 +0800 Subject: [PATCH] [Watch] Support watch --- examples/Makefile | 2 + examples/watch_list_pod/.gitignore | 1 + examples/watch_list_pod/Makefile | 8 +++ examples/watch_list_pod/main.c | 110 +++++++++++++++++++++++++++++ kubernetes/CMakeLists.txt | 2 + kubernetes/src/apiClient.c | 1 + kubernetes/watch/watch_util.c | 65 +++++++++++++++++ kubernetes/watch/watch_util.h | 15 ++++ 8 files changed, 204 insertions(+) create mode 100644 examples/watch_list_pod/.gitignore create mode 100644 examples/watch_list_pod/Makefile create mode 100644 examples/watch_list_pod/main.c create mode 100644 kubernetes/watch/watch_util.c create mode 100644 kubernetes/watch/watch_util.h diff --git a/examples/Makefile b/examples/Makefile index 9878207..dce24b3 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -5,6 +5,7 @@ all: cd exec_provider; make cd generic; make cd auth_provider; make + cd watch_list_pod; make clean: cd create_pod; make clean @@ -13,3 +14,4 @@ clean: cd exec_provider; make clean cd generic; make clean cd auth_provider; make clean + cd watch_list_pod; make clean diff --git a/examples/watch_list_pod/.gitignore b/examples/watch_list_pod/.gitignore new file mode 100644 index 0000000..5844e06 --- /dev/null +++ b/examples/watch_list_pod/.gitignore @@ -0,0 +1 @@ +watch_list_pod_bin diff --git a/examples/watch_list_pod/Makefile b/examples/watch_list_pod/Makefile new file mode 100644 index 0000000..df3b28f --- /dev/null +++ b/examples/watch_list_pod/Makefile @@ -0,0 +1,8 @@ +INCLUDE:=-I../../kubernetes/include -I../../kubernetes/model -I../../kubernetes/api -I../../kubernetes/config -I../../kubernetes/watch +LIBS:=-L../../kubernetes/build -lkubernetes -lcurl -lyaml -lpthread -lssl -lz +CFLAGS:=-g + +all: + gcc main.c $(CFLAGS) $(INCLUDE) $(LIBS) -o watch_list_pod_bin +clean: + rm ./watch_list_pod_bin diff --git a/examples/watch_list_pod/main.c b/examples/watch_list_pod/main.c new file mode 100644 index 0000000..debe685 --- /dev/null +++ b/examples/watch_list_pod/main.c @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include +#include +#include + +#define WATCH_EVENT_KEY_TYPE "type" +#define WATCH_EVENT_KEY_OBJECT "object" + +void on_pod_event_comes(const char *event_string) +{ + static char fname[] = "process_one_watch_event()"; + + if (!event_string) { + return; + } + printf("\nwatch event raw string:\n%s\n\n", event_string); + + cJSON *event_json_obj = cJSON_Parse(event_string); + if (!event_json_obj) { + fprintf(stderr, "%s: Cannot create JSON from string.[%s].\n", fname, cJSON_GetErrorPtr()); + goto end; + } + + cJSON *json_value_type = cJSON_GetObjectItem(event_json_obj, WATCH_EVENT_KEY_TYPE); + if (!json_value_type || json_value_type->type != cJSON_String) { + fprintf(stderr, "%s: Cannot get type in watch event.\n", fname); + goto end; + } + char *type = strdup(json_value_type->valuestring); + printf("type: %s\n", type); + + cJSON *json_value_object = cJSON_GetObjectItem(event_json_obj, WATCH_EVENT_KEY_OBJECT); + if (!json_value_object || json_value_object->type != cJSON_Object) { + fprintf(stderr, "%s: Cannot get object in watch event.\n", fname); + goto end; + } + v1_pod_t *pod = v1_pod_parseFromJSON(json_value_object); + if (!pod) { + fprintf(stderr, "%s: Cannot get pod from watch event object.\n", fname); + goto end; + } + printf("pod:\n\tname: %s\n", pod->metadata->name); + + end: + if (pod) { + v1_pod_free(pod); + pod = NULL; + } + if (type) { + free(type); + type = NULL; + } + if (event_json_obj) { + cJSON_Delete(event_json_obj); + event_json_obj = NULL; + } +} + +void my_pod_watch_handler(void **pData, long *pDataLen) +{ + kubernets_watch_handler(pData, pDataLen, on_pod_event_comes); +} + +void watch_list_pod(apiClient_t * apiClient) +{ + apiClient->data_callback_func = my_pod_watch_handler; + + CoreV1API_listNamespacedPod(apiClient, "default", /*namespace */ + NULL, /* pretty */ + 0, /* allowWatchBookmarks */ + NULL, /* continue */ + NULL, /* fieldSelector */ + NULL, /* labelSelector */ + 0, /* limit */ + NULL, /* resourceVersion */ + 0, /* timeoutSeconds */ + 1 /* watch */ + ); +} + +int main(int argc, char *argv[]) +{ + char *basePath = NULL; + sslConfig_t *sslConfig = NULL; + list_t *apiKeys = NULL; + int rc = load_kube_config(&basePath, &sslConfig, &apiKeys, NULL); /* NULL means loading configuration from $HOME/.kube/config */ + if (rc != 0) { + printf("Cannot load kubernetes configuration.\n"); + return -1; + } + apiClient_t *apiClient = apiClient_create_with_base_path(basePath, sslConfig, apiKeys); + if (!apiClient) { + printf("Cannot create a kubernetes client.\n"); + return -1; + } + + watch_list_pod(apiClient); + + apiClient_free(apiClient); + apiClient = NULL; + free_client_config(basePath, sslConfig, apiKeys); + basePath = NULL; + sslConfig = NULL; + apiKeys = NULL; + + return 0; +} diff --git a/kubernetes/CMakeLists.txt b/kubernetes/CMakeLists.txt index f658ecf..bab1aa1 100644 --- a/kubernetes/CMakeLists.txt +++ b/kubernetes/CMakeLists.txt @@ -40,6 +40,7 @@ set(SRCS config/exec_provider.c config/authn_plugin/authn_plugin_util.c config/authn_plugin/authn_plugin.c + watch/watch_util.c src/list.c src/apiKey.c src/apiClient.c @@ -802,6 +803,7 @@ set(HDRS config/exec_provider.h config/authn_plugin/authn_plugin_util.h config/authn_plugin/authn_plugin.h + watch/watch_util.h include/apiClient.h include/list.h include/binary.h diff --git a/kubernetes/src/apiClient.c b/kubernetes/src/apiClient.c index 5be4ac1..4784d89 100644 --- a/kubernetes/src/apiClient.c +++ b/kubernetes/src/apiClient.c @@ -76,6 +76,7 @@ void apiClient_free(apiClient_t *apiClient) { } list_free(apiClient->apiKeys_BearerToken); } + free(apiClient); curl_global_cleanup(); } diff --git a/kubernetes/watch/watch_util.c b/kubernetes/watch/watch_util.c new file mode 100644 index 0000000..b68da48 --- /dev/null +++ b/kubernetes/watch/watch_util.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include +#include "../include/list.h" +#include "watch_util.h" + +#define JSON_ARRAY_DELIM "\r\n" + +static int wu_convert_to_json_array(list_t * json_array, const char *json_string) +{ + if (!json_string || '\0' == json_string[0] || !json_array) { + return -1; + } + + int rc = 0; + char *json_string_dup = strdup(json_string); + + char *token = NULL; + token = strtok(json_string_dup, JSON_ARRAY_DELIM); + while (token) { + cJSON *cjson = cJSON_Parse(token); + if (cjson == NULL) { + rc = -1; + goto end; + } + list_addElement(json_array, strdup(token)); + token = strtok(NULL, JSON_ARRAY_DELIM); + } + + end: + if (json_string_dup) { + free(json_string_dup); + json_string_dup = NULL; + } + return rc; +} + +void kubernets_watch_handler(void **pData, long *pDataLen, KUBE_WATCH_EVENT_HANDLER_FUNC event_hander) +{ + char *data = *(char **) pData; + + list_t *watch_event_list = list_create(); + if (!watch_event_list) { + fprintf(stderr, "Cannot create a list for watch events.\n"); + return; + } + int rc = wu_convert_to_json_array(watch_event_list, data); + if (0 == rc) { + + listEntry_t *listEntry = NULL; + list_ForEach(listEntry, watch_event_list) { + char *list_item = listEntry->data; + event_hander(list_item); + } + + free(data); + *pData = NULL; + *pDataLen = 0; + } + + clear_and_free_string_list(watch_event_list); + watch_event_list = NULL; +} diff --git a/kubernetes/watch/watch_util.h b/kubernetes/watch/watch_util.h new file mode 100644 index 0000000..b99d7d5 --- /dev/null +++ b/kubernetes/watch/watch_util.h @@ -0,0 +1,15 @@ +#ifndef _WATCH_UTIL_H +#define _WATCH_UTIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*KUBE_WATCH_EVENT_HANDLER_FUNC)(const char*); + +void kubernets_watch_handler(void** pData, long* pDataLen, KUBE_WATCH_EVENT_HANDLER_FUNC event_hander); + +#ifdef __cplusplus +} +#endif +#endif /* _WATCH_UTIL_H */