From 40006332027b7f9769862063f9cbc305c4518694 Mon Sep 17 00:00:00 2001 From: Brendan Burns Date: Fri, 14 Aug 2020 10:56:05 -0700 Subject: [PATCH] Add a generic client (read-only for now) --- examples/generic/.gitignore | 1 + examples/generic/Makefile | 8 ++++ examples/generic/main.c | 44 +++++++++++++++++ kubernetes/CMakeLists.txt | 1 + kubernetes/include/generic.h | 22 +++++++++ kubernetes/src/generic.c | 91 ++++++++++++++++++++++++++++++++++++ 6 files changed, 167 insertions(+) create mode 100644 examples/generic/.gitignore create mode 100644 examples/generic/Makefile create mode 100644 examples/generic/main.c create mode 100644 kubernetes/include/generic.h create mode 100644 kubernetes/src/generic.c diff --git a/examples/generic/.gitignore b/examples/generic/.gitignore new file mode 100644 index 0000000..d16b789 --- /dev/null +++ b/examples/generic/.gitignore @@ -0,0 +1 @@ +generic_bin diff --git a/examples/generic/Makefile b/examples/generic/Makefile new file mode 100644 index 0000000..873e2f6 --- /dev/null +++ b/examples/generic/Makefile @@ -0,0 +1,8 @@ +INCLUDE:=-I../../kubernetes/include -I../../kubernetes/model -I../../kubernetes/api -I../../kubernetes/config +LIBS:=-L../../kubernetes/build -lkubernetes -lcurl -lyaml -lpthread -lssl -lz +CFLAGS:=-g + +all: + gcc main.c $(CFLAGS) $(INCLUDE) $(LIBS) -o generic_bin +clean: + rm ./generic_bin diff --git a/examples/generic/main.c b/examples/generic/main.c new file mode 100644 index 0000000..0f3cb2a --- /dev/null +++ b/examples/generic/main.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include +#include + +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; + } + + genericClient_t *genericClient = genericClient_create(apiClient, "apps", "v1", "deployments"); + + char *list = Generic_listNamespaced(genericClient, "default"); + printf("%s\n", list); + free(list); + + char *result = Generic_readNamespacedResource(genericClient, "default", "camera-gc"); + printf("%s\n", result); + free(result); + + genericClient_free(genericClient); + genericClient = NULL; + 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 c1e05aa..7c53bcd 100644 --- a/kubernetes/CMakeLists.txt +++ b/kubernetes/CMakeLists.txt @@ -41,6 +41,7 @@ set(SRCS src/apiKey.c src/apiClient.c src/binary.c + src/generic.c external/cJSON.c model/object.c model/admissionregistration_v1_service_reference.c diff --git a/kubernetes/include/generic.h b/kubernetes/include/generic.h new file mode 100644 index 0000000..15dc645 --- /dev/null +++ b/kubernetes/include/generic.h @@ -0,0 +1,22 @@ +#ifndef __GENERIC_H__ +#define __GENERIC_H__ + +#include "../include/apiClient.h" + +typedef struct genericClient_t { + apiClient_t *client; + char *apiGroup; + char *apiVersion; + char *resourcePlural; +} genericClient_t; + +genericClient_t* genericClient_create(apiClient_t *client, const char *apiGroup, const char* apiVersion, const char* resourcePlural); +void genericClient_free(genericClient_t* client); + +char* Generic_readNamespacedResource(genericClient_t *client, const char *ns, const char *name); +char* Generic_readResource(genericClient_t *client, const char *name); + +char* Generic_listNamespaced(genericClient_t *client, const char *ns); +char* Generic_list(genericClient_t *client); + +#endif \ No newline at end of file diff --git a/kubernetes/src/generic.c b/kubernetes/src/generic.c new file mode 100644 index 0000000..5db950b --- /dev/null +++ b/kubernetes/src/generic.c @@ -0,0 +1,91 @@ +#include "../include/apiClient.h" +#include "../include/generic.h" + +genericClient_t* genericClient_create(apiClient_t *client, const char *apiGroup, const char* apiVersion, const char* resourcePlural) { + genericClient_t *result = malloc(sizeof(genericClient_t)); + result->client = client; + result->apiGroup = strdup(apiGroup); + result->apiVersion = strdup(apiVersion); + result->resourcePlural = strdup(resourcePlural); + + return result; +} + +void genericClient_free(genericClient_t* client) { + free(client->apiGroup); + free(client->apiVersion); + free(client->resourcePlural); + free(client); +} + +void makeNamespacedResourcePath(char* path, genericClient_t *client, const char* namespace, const char* name) { + snprintf( + path, 128, + "/apis/%s/%s/namespaces/%s/%s/%s", + client->apiGroup, + client->apiVersion, + namespace, + client->resourcePlural, + name + ); +} + +void makeResourcePath(char* path, genericClient_t *client, const char* name) { + snprintf( + path, 128, + "/apis/%s/%s/%s/%s", + client->apiGroup, + client->apiVersion, + client->resourcePlural, + name + ); +} + +char* readInternal(genericClient_t *client, const char* path) { + apiClient_invoke(client->client, path, NULL, NULL, NULL, NULL, NULL, NULL, "GET"); + + if (client->client->response_code == 200) { + printf("%s\n","OK"); + } + if (client->client->response_code == 401) { + printf("%s\n","Unauthorized"); + return NULL; + } + char* elementToReturn = strndup((char*)client->client->dataReceived, client->client->dataReceivedLen); + + if (client->client->dataReceived) { + free(client->client->dataReceived); + client->client->dataReceived = NULL; + client->client->dataReceivedLen = 0; + } + + return elementToReturn; +} + +char* Generic_readNamespacedResource(genericClient_t *client, const char *namespace, const char *name) { + char path[128]; + + makeNamespacedResourcePath(path, client, namespace, name); + return readInternal(client, path); +} + +char* Generic_readResource(genericClient_t *client, const char *name) { + char path[128]; + + makeResourcePath(path, client, name); + return readInternal(client, path); +} + +char *Generic_listNamespaced(genericClient_t *client, const char *namespace) { + char path[128]; + snprintf(path, 128, "/apis/%s/%s/namespaces/%s/%s", + client->apiGroup, client->apiVersion, namespace, client->resourcePlural); + readInternal(client, path); +} + +char *Generic_list(genericClient_t *client) { + char path[128]; + snprintf(path, 128, "/apis/%s/%s", client->apiGroup, client->apiVersion, client->resourcePlural); + readInternal(client, path); +} +