From 705a605e9517b9b4bb8e1e4fb385b953f37c55b8 Mon Sep 17 00:00:00 2001 From: Hui Yu Date: Sun, 5 Apr 2020 19:34:24 +0800 Subject: [PATCH 1/2] [Configuration]Support configuration for X509 client certificate in kube config file --- code-check/code-static-check.sh | 5 + examples/create_pod/Makefile | 4 +- examples/create_pod/main.c | 89 ++---- examples/list_pod/Makefile | 4 +- examples/list_pod/main.c | 97 ++---- kubernetes/CMakeLists.txt | 8 + kubernetes/config/kube_config.c | 309 +++++++++++++++++++ kubernetes/config/kube_config.h | 82 ++++++ kubernetes/config/kube_config_model.c | 264 +++++++++++++++++ kubernetes/config/kube_config_model.h | 89 ++++++ kubernetes/config/kube_config_yaml.c | 407 ++++++++++++++++++++++++++ kubernetes/config/kube_config_yaml.h | 37 +++ 12 files changed, 1263 insertions(+), 132 deletions(-) create mode 100644 code-check/code-static-check.sh create mode 100644 kubernetes/config/kube_config.c create mode 100644 kubernetes/config/kube_config.h create mode 100644 kubernetes/config/kube_config_model.c create mode 100644 kubernetes/config/kube_config_model.h create mode 100644 kubernetes/config/kube_config_yaml.c create mode 100644 kubernetes/config/kube_config_yaml.h diff --git a/code-check/code-static-check.sh b/code-check/code-static-check.sh new file mode 100644 index 0000000..6774573 --- /dev/null +++ b/code-check/code-static-check.sh @@ -0,0 +1,5 @@ +# Usage: +# sh ./code-static-check.sh ${source_dir} + +cppcheck --enable=all $* + diff --git a/examples/create_pod/Makefile b/examples/create_pod/Makefile index 6387394..8137440 100644 --- a/examples/create_pod/Makefile +++ b/examples/create_pod/Makefile @@ -1,5 +1,5 @@ -INCLUDE:=-I../../kubernetes/include -I../../kubernetes/model -I../../kubernetes/api -LIBS:=-L../../kubernetes/build -lkubernetes -lcurl -lpthread -lssl -lz +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: diff --git a/examples/create_pod/main.c b/examples/create_pod/main.c index 8242c03..df74b00 100644 --- a/examples/create_pod/main.c +++ b/examples/create_pod/main.c @@ -1,22 +1,10 @@ +#include #include #include #include #include #include -// kubectl proxy server -#define K8S_APISERVER_BASEPATH "http://localhost:8001" - -// Alternately from within a Kubernetes cluster: -// #define K8S_APISERVER_BASEPATH https://your.server.here - -#define K8S_TOKEN_FILE_IN_CLUSTER "/var/run/secrets/kubernetes.io/serviceaccount/token" -#define K8S_TOKEN_BUF_SIZE 1024 -#define K8S_AUTH_KEY "Authorization" -#define K8S_AUTH_VALUE_TEMPLATE "Bearer %s" - -apiClient_t *g_k8sAPIConnector; - void create_a_pod(apiClient_t * apiClient) { char *namespace = "default"; @@ -54,57 +42,34 @@ void create_a_pod(apiClient_t * apiClient) v1_pod_free(apod); } -int loadK8sConfigInCluster(char *token, int token_buf_size) -{ - static char fname[] = "loadK8sConfigInCluster()"; - - FILE *fp; - fp = fopen(K8S_TOKEN_FILE_IN_CLUSTER, "r"); - - if (fp == NULL) { - if (errno == ENOENT) { - printf("%s: The file %s does not exist.", fname, K8S_TOKEN_FILE_IN_CLUSTER); - return (-1); - } else { - printf("%s: Failed to open file %s.", fname, K8S_TOKEN_FILE_IN_CLUSTER); - return (-1); - } - } - - while (fgets(token, token_buf_size, fp) != NULL) { - ; - } - - printf("%s\n", token); - - fclose(fp); - - return 0; -} - -int init_k8s_connector(const char *token_out_of_cluster) -{ - list_t *apiKeys; - apiKeys = list_create(); - - char *keyToken = strdup(K8S_AUTH_KEY); - - char valueToken[K8S_TOKEN_BUF_SIZE]; - memset(valueToken, 0, sizeof(valueToken)); - - sprintf(valueToken, K8S_AUTH_VALUE_TEMPLATE, token_out_of_cluster); - - keyValuePair_t *keyPairToken = keyValuePair_create(keyToken, valueToken); - list_addElement(apiKeys, keyPairToken); - - g_k8sAPIConnector = apiClient_create_with_base_path(K8S_APISERVER_BASEPATH, NULL, apiKeys); -} - int main(int argc, char *argv[]) { - init_k8s_connector(argv[1]); - create_a_pod(g_k8sAPIConnector); + int rc = 0; + + char *baseName = NULL; + sslConfig_t *sslConfig = NULL; + list_t *apiKeys = NULL; + apiClient_t *k8sApiClient = NULL; + + rc = load_kube_config(&baseName, &sslConfig, &apiKeys, NULL); + if (0 == rc) { + k8sApiClient = apiClient_create_with_base_path(baseName, sslConfig, apiKeys); + } else { + printf("Cannot load kubernetes configuration.\n"); + return -1; + } + + if (k8sApiClient) { + create_a_pod(k8sApiClient); + } + + free_client_config(baseName, sslConfig, apiKeys); + baseName = NULL; + sslConfig = NULL; + apiKeys = NULL; + + apiClient_free(k8sApiClient); + k8sApiClient = NULL; - apiClient_free(g_k8sAPIConnector); } diff --git a/examples/list_pod/Makefile b/examples/list_pod/Makefile index 477785f..eee7d05 100644 --- a/examples/list_pod/Makefile +++ b/examples/list_pod/Makefile @@ -1,5 +1,5 @@ -INCLUDE:=-I../../kubernetes/include -I../../kubernetes/model -I../../kubernetes/api -LIBS:=-L../../kubernetes/build -lkubernetes -lcurl -lpthread -lssl -lz +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: diff --git a/examples/list_pod/main.c b/examples/list_pod/main.c index 9693a86..4ed94a9 100644 --- a/examples/list_pod/main.c +++ b/examples/list_pod/main.c @@ -1,22 +1,10 @@ +#include #include #include #include #include #include -// kubectl proxy server -#define K8S_APISERVER_BASEPATH "http://localhost:8001" - -// Alternately from within a Kubernetes cluster: -// #define K8S_APISERVER_BASEPATH https://your.server.here - -#define K8S_TOKEN_FILE_IN_CLUSTER "/var/run/secrets/kubernetes.io/serviceaccount/token" -#define K8S_TOKEN_BUF_SIZE 1024 -#define K8S_AUTH_KEY "Authorization" -#define K8S_AUTH_VALUE_TEMPLATE "Bearer %s" - -apiClient_t *g_k8sAPIConnector; - void list_pod(apiClient_t * apiClient) { v1_pod_list_t *pod_list = NULL; @@ -31,71 +19,48 @@ void list_pod(apiClient_t * apiClient) 0, /* timeoutSeconds */ 0 /* watch */ ); - printf("return code=%ld\n", apiClient->response_code); + printf("The return code of HTTP request=%ld\n", apiClient->response_code); if (pod_list) { - printf("Get pod list.\n"); + printf("Get pod list:\n"); listEntry_t *listEntry = NULL; v1_pod_t *pod = NULL; list_ForEach(listEntry, pod_list->items) { pod = listEntry->data; - printf("pod name=%s\n", pod->metadata->name); + printf("\tThe pod name: %s\n", pod->metadata->name); } } else { - printf("Cannot list any pod.\n"); + printf("Cannot get any pod.\n"); } } -int loadK8sConfigInCluster(char *token, int token_buf_size) -{ - static char fname[] = "loadK8sConfigInCluster()"; - - FILE *fp; - fp = fopen(K8S_TOKEN_FILE_IN_CLUSTER, "r"); - - if (fp == NULL) { - if (errno == ENOENT) { - printf("%s: The file %s does not exist.", fname, K8S_TOKEN_FILE_IN_CLUSTER); - return (-1); - } else { - printf("%s: Failed to open file %s.", fname, K8S_TOKEN_FILE_IN_CLUSTER); - return (-1); - } - } - - while (fgets(token, token_buf_size, fp) != NULL) { - ; - } - - printf("%s\n", token); - - fclose(fp); - - return 0; -} - -int init_k8s_connector(const char *token_out_of_cluster) -{ - list_t *apiKeys; - apiKeys = list_create(); - - char *keyToken = strdup(K8S_AUTH_KEY); - - char valueToken[K8S_TOKEN_BUF_SIZE]; - memset(valueToken, 0, sizeof(valueToken)); - - sprintf(valueToken, K8S_AUTH_VALUE_TEMPLATE, token_out_of_cluster); - - keyValuePair_t *keyPairToken = keyValuePair_create(keyToken, valueToken); - list_addElement(apiKeys, keyPairToken); - - g_k8sAPIConnector = apiClient_create_with_base_path(K8S_APISERVER_BASEPATH, NULL, apiKeys); -} - int main(int argc, char *argv[]) { - init_k8s_connector(argv[1]); + int rc = 0; - list_pod(g_k8sAPIConnector); + char *baseName = NULL; + sslConfig_t *sslConfig = NULL; + list_t *apiKeys = NULL; + apiClient_t *k8sApiClient = NULL; - apiClient_free(g_k8sAPIConnector); + rc = load_kube_config(&baseName, &sslConfig, &apiKeys, NULL); + if (0 == rc) { + k8sApiClient = apiClient_create_with_base_path(baseName, sslConfig, apiKeys); + } else { + printf("Cannot load kubernetes configuration.\n"); + return -1; + } + + if (k8sApiClient) { + list_pod(k8sApiClient); + } + + free_client_config(baseName, sslConfig, apiKeys); + baseName = NULL; + sslConfig = NULL; + apiKeys = NULL; + + apiClient_free(k8sApiClient); + k8sApiClient = NULL; + + return rc; } diff --git a/kubernetes/CMakeLists.txt b/kubernetes/CMakeLists.txt index 28f240c..4f29d96 100644 --- a/kubernetes/CMakeLists.txt +++ b/kubernetes/CMakeLists.txt @@ -9,6 +9,7 @@ set(CMAKE_VISIBILITY_INLINES_HIDDEN OFF) set(CMAKE_BUILD_TYPE Debug) set(pkgName "kubernetes") +ADD_DEFINITIONS(-DOPENSSL) find_package(CURL 7.58.0 REQUIRED) if(CURL_FOUND) @@ -18,7 +19,11 @@ else(CURL_FOUND) message(FATAL_ERROR "Could not find the CURL library and development files.") endif() + set(SRCS + config/kube_config_model.c + config/kube_config_yaml.c + config/kube_config.c src/list.c src/apiKey.c src/apiClient.c @@ -770,6 +775,9 @@ set(SRCS ) set(HDRS + config/kube_config_model.h + config/kube_config_yaml.h + config/kube_config.h include/apiClient.h include/list.h include/keyValuePair.h diff --git a/kubernetes/config/kube_config.c b/kubernetes/config/kube_config.c new file mode 100644 index 0000000..130a192 --- /dev/null +++ b/kubernetes/config/kube_config.c @@ -0,0 +1,309 @@ +#include "kube_config.h" +#include "kube_config_yaml.h" +#include +#include + +#define ENV_KUBECONFIGE "KUBECONFIG" +#define ENV_HOME "HOME" +#define KUBE_CONFIG_DEFAULT_LOCATION "%s/.kube/config" +#define KUBE_CONFIG_TEMPFILE_NAME_TEMPLATE "/tmp/kubeconfig-XXXXXX" + +static int setBasePath(char **pBasePath, char *basePath) +{ + int rc = 0; + char *_basePath = strdup(basePath); + if (_basePath) { + *pBasePath = _basePath; + } else { + rc = -1; + } + return rc; + +} + +static char *kubeconfig_mk_cert_key_tempfile(const char *b64data) +{ + static char fname[] = "kubeconfig_mk_tempfile()"; + + int decoded_bytes = 0; + char *b64decode = base64decode(b64data, strlen(b64data), &decoded_bytes); + if (!b64decode || 0 == decoded_bytes) { + fprintf(stderr, "%s: Base64 decodes failed.\n", fname); + return NULL; + } + + char tempfile_name_template[] = KUBE_CONFIG_TEMPFILE_NAME_TEMPLATE; + int fd = mkstemp(tempfile_name_template); + if (-1 == fd) { + fprintf(stderr, "%s: Creating temp file for kubeconfig failed with error [%s]\n", fname, strerror(errno)); + return NULL; + } + + if (-1 == write(fd, b64decode, decoded_bytes)) { + fprintf(stderr, "%s: Writing temp file failed with error [%s]\n", fname, strerror(errno)); + close(fd); + return NULL; + } + + close(fd); + + return strdup(tempfile_name_template); +} + +static void kubeconfig_rm_tempfile(const char *filename) +{ + if (filename) { + unlink(filename); + } +} + +static void unsetSslConfig(sslConfig_t * sslConfig) +{ + if (!sslConfig) { + return; + } + + if (sslConfig->clientCertFile) { + kubeconfig_rm_tempfile(sslConfig->clientCertFile); + } + if (sslConfig->clientKeyFile) { + kubeconfig_rm_tempfile(sslConfig->clientKeyFile); + } + if (sslConfig->CACertFile) { + kubeconfig_rm_tempfile(sslConfig->CACertFile); + } + +} + +static int setSslConfig(sslConfig_t ** pSslConfig, kubeconfig_cluster_t * cluster, kubeconfig_user_t * user) +{ + int rc = 0; + char *client_cert_file = NULL; + char *client_key_file = NULL; + char *ca_file = NULL; + int insecure_skip_tls_verify = 0; + + if (user) { + if (user->client_certificate_data) { + client_cert_file = kubeconfig_mk_cert_key_tempfile(user->client_certificate_data); + } + if (user->client_key_data) { + client_key_file = kubeconfig_mk_cert_key_tempfile(user->client_key_data); + } + insecure_skip_tls_verify = user->insecure_skip_tls_verify; + } + + if (cluster) { + if ((0 == insecure_skip_tls_verify) && (cluster->certificate_authority_data)) { + ca_file = kubeconfig_mk_cert_key_tempfile(cluster->certificate_authority_data); + } + } + + sslConfig_t *sc = sslConfig_create(client_cert_file, client_key_file, ca_file, insecure_skip_tls_verify); + if (sc) { + *pSslConfig = sc; + } else { + rc = -1; + } + + if (client_cert_file) { + free(client_cert_file); + } + if (client_key_file) { + free(client_key_file); + } + if (ca_file) { + free(ca_file); + } + + return rc; +} + +static int setApiKeys(list_t ** pApiKeys, kubeconfig_user_t * user) +{ + int rc = 0; + list_t *apiKeys = list_create(); + if (apiKeys) { + + /* under development for the token based authentication */ + + *pApiKeys = apiKeys; + } else { + rc = -1; + } + return rc; +} + +static char *getWorkingConfigFile(const char *configFileNamePassedIn) +{ + char *configFileName = NULL; + const char *kubeconfig_env = NULL; + const char *homedir_env = NULL; + + if (configFileNamePassedIn) { + configFileName = strdup(configFileNamePassedIn); + } else { + kubeconfig_env = getenv(ENV_KUBECONFIGE); + if (kubeconfig_env) { + configFileName = strdup(kubeconfig_env); + } else { + homedir_env = getenv(ENV_HOME); + if (homedir_env) { + configFileName = calloc(strlen(homedir_env) + strlen(KUBE_CONFIG_DEFAULT_LOCATION) + 1, sizeof(char)); + if (configFileName) { + sprintf(configFileName, KUBE_CONFIG_DEFAULT_LOCATION, homedir_env); + } + } + } + } + + return configFileName; +} + +static kubeconfig_context_t *kubeconfig_get_current_context(kubeconfig_context_t ** contexts, int contexts_count, const char *current_context_str) +{ + kubeconfig_context_t *current_context = NULL; + + if (NULL == contexts || NULL == current_context_str) { + return NULL; + } + + int i = 0; + for (i = 0; i < contexts_count; i++) { + if (0 == strcmp(contexts[i]->name, current_context_str)) { + current_context = contexts[i]; + break; + } + } + + return current_context; +} + +static kubeconfig_cluster_t *kubeconfig_get_current_cluster(kubeconfig_cluster_t ** clusters, int clusters_count, const char *cluster_name) +{ + kubeconfig_cluster_t *current_cluster = NULL; + + if (NULL == clusters || NULL == cluster_name) { + return NULL; + } + + int i = 0; + for (i = 0; i < clusters_count; i++) { + if (0 == strcmp(clusters[i]->name, cluster_name)) { + current_cluster = clusters[i]; + break; + } + } + + return current_cluster; +} + +static kubeconfig_user_t *kubeconfig_get_current_user(kubeconfig_user_t ** users, int users_count, const char *user_name) +{ + kubeconfig_user_t *current_user = NULL; + + if (NULL == users || NULL == user_name) { + return NULL; + } + + int i = 0; + for (i = 0; i < users_count; i++) { + if (0 == strcmp(users[i]->name, user_name)) { + current_user = users[i]; + break; + } + } + + return current_user; +} + +int load_kube_config(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApiKeys, const char *configFileName) +{ + static char fname[] = "load_kube_config()"; + + int rc = 0; + + kubeconfig_context_t *current_context = NULL; + kubeconfig_cluster_t *current_cluster = NULL; + kubeconfig_user_t *current_user = NULL; + + kubeconfig_t *kubeconfig = kubeconfig_create(); + if (!kubeconfig) { + fprintf(stderr, "%s: Cannot create kubeconfig.[%s]\n", fname, strerror(errno)); + return -1; + } + + kubeconfig->fileName = getWorkingConfigFile(configFileName); + rc = kubeyaml_load_kubeconfig(kubeconfig); + if (0 != rc) { + fprintf(stderr, "%s: Cannot load the kubeconfig %s\n", fname, kubeconfig->fileName); + rc = -1; + goto end; + } + + current_context = kubeconfig_get_current_context(kubeconfig->contexts, kubeconfig->contexts_count, kubeconfig->current_context); + if (!current_context) { + fprintf(stderr, "%s: Cannot get the current context by the kubeconfig.\n", fname); + rc = -1; + goto end; + } + + current_cluster = kubeconfig_get_current_cluster(kubeconfig->clusters, kubeconfig->clusters_count, current_context->cluster); + if (!current_cluster) { + fprintf(stderr, "%s: Cannot get the current cluster information by the kubeconfig.\n", fname); + rc = -1; + goto end; + } + + current_user = kubeconfig_get_current_user(kubeconfig->users, kubeconfig->users_count, current_context->user); + if (!current_user) { + fprintf(stderr, "%s: Cannot get the current user information by the kubeconfig.\n", fname); + rc = -1; + goto end; + } + + if (current_cluster && current_cluster->server) { + rc = setBasePath(pBasePath, current_cluster->server); + if (0 != rc) { + fprintf(stderr, "%s: Cannot set the base path for API server.\n", fname); + goto end; + } + } + + if (current_cluster || current_user) { + rc = setSslConfig(pSslConfig, current_cluster, current_user); + if (0 != rc) { + fprintf(stderr, "%s: Cannot set the SSL Configuration for the client.\n", fname); + goto end; + } + } + + if (current_user) { + rc = setApiKeys(pApiKeys, current_user); + if (0 != rc) { + fprintf(stderr, "%s: Cannot set the tokens for the client.\n", fname); + goto end; + } + } + + end: + kubeconfig_free(kubeconfig); + kubeconfig = NULL; + return rc; +} + +void free_client_config(char *basePath, sslConfig_t * sslConfig, list_t * apiKeys) +{ + if (basePath) { + free(basePath); + } + + if (sslConfig) { + unsetSslConfig(sslConfig); + sslConfig_free(sslConfig); + } + + if (apiKeys) { + list_free(apiKeys); + } +} diff --git a/kubernetes/config/kube_config.h b/kubernetes/config/kube_config.h new file mode 100644 index 0000000..96a9fb5 --- /dev/null +++ b/kubernetes/config/kube_config.h @@ -0,0 +1,82 @@ +#ifndef _KUBE_CONFIG_H +#define _KUBE_CONFIG_H + +#include "../include/apiClient.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * load_kube_config + * + * + * Description: + * + * + * Load kubernetes cluster configuration from the file specified + * by parameter or default location: $HOME/.kube/config + * + * + * Return: + * + * 0 Success + * -1 Failed + * + * + * Parameter: + * + * + * IN: + + * configFileName : kubernetes cluster configuration file name + * + * + * OUT: + * + * pBasePath: The pointer to API server address + * pSslConfig: The pointer to SSL configuration for client + * pApiKeys: The pointer to API tokens for client + * + * The memory will be allocated inside this function. User + * should call free_client_config to free the memory after + * these parameters are not used. + * + */ + +int load_kube_config(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApiKeys, const char *configFileName); + +/* + * free_client_config + * + * + * Description: + * + * Help function to free the memory for the client configuration + * + * + * Return: + * + * None + * + * + * Parameter: + * + * IN: + * + * basePath: API server address + * sslConfig: SSL configuration for client + * apiKeys: API tokens for client + * + * OUT: + * + * None + * + */ + +void free_client_config(char *basePath, sslConfig_t * sslConfig, list_t * apiKeys); + +#ifdef __cplusplus +} +#endif +#endif /* _KUBE_CONFIG_H */ diff --git a/kubernetes/config/kube_config_model.c b/kubernetes/config/kube_config_model.c new file mode 100644 index 0000000..555f00a --- /dev/null +++ b/kubernetes/config/kube_config_model.c @@ -0,0 +1,264 @@ +#include "kube_config_model.h" +#include + +kubeconfig_auth_provider_t *kubeconfig_auth_provider_create() +{ + kubeconfig_auth_provider_t *provider = calloc(1, sizeof(kubeconfig_auth_provider_t)); + return provider; +} + +void kubeconfig_auth_provider_free(kubeconfig_auth_provider_t * provider) +{ + if (!provider) { + return; + } + + if (provider->name) { + free(provider->name); + } + if (provider->id_token) { + free(provider->id_token); + } + if (provider->cmd_path) { + free(provider->cmd_path); + } + if (provider->access_token) { + free(provider->access_token); + } + if (provider->expires_on) { + free(provider->expires_on); + } + if (provider->expiry) { + free(provider->expiry); + } + if (provider->idp_certificate_authority_data) { + free(provider->idp_certificate_authority_data); + } + + free(provider); +} + +kubeconfig_exec_t *kubeconfig_exec_create() +{ + kubeconfig_exec_t *exec = calloc(1, sizeof(kubeconfig_exec_t)); + return exec; +} + +void kubeconfig_exec_free(kubeconfig_exec_t * exec) +{ + if (!exec) { + return; + } + + if (exec->command) { + free(exec->command); + } + + free(exec); +} + +kubeconfig_cluster_t *kubeconfig_cluster_create() +{ + kubeconfig_cluster_t *cluster = calloc(1, sizeof(kubeconfig_cluster_t)); + return cluster; +} + +void kubeconfig_cluster_free(kubeconfig_cluster_t * cluster) +{ + if (!cluster) { + return; + } + + if (cluster->name) { + free(cluster->name); + } + if (cluster->server) { + free(cluster->server); + } + if (cluster->certificate_authority_data) { + free(cluster->certificate_authority_data); + } + + free(cluster); +} + +kubeconfig_cluster_t **kubeconfig_clusters_create(int clusters_count) +{ + kubeconfig_cluster_t **clusters = (kubeconfig_cluster_t **) calloc(clusters_count, sizeof(kubeconfig_cluster_t *)); + int i = 0; + for (i = 0; i < clusters_count; i++) { + clusters[i] = kubeconfig_cluster_create(); + } + return clusters; +} + +void kubeconfig_clusters_free(kubeconfig_cluster_t ** clusters, int cluster_count) +{ + if (!clusters) { + return; + } + + int i = 0; + for (i = 0; i < cluster_count; i++) { + if (clusters[i]) { + kubeconfig_cluster_free(clusters[i]); + clusters[i] = NULL; + } + } + free(clusters); +} + +kubeconfig_user_t *kubeconfig_user_create() +{ + kubeconfig_user_t *user = calloc(1, sizeof(kubeconfig_user_t)); + return user; +} + +void kubeconfig_user_free(kubeconfig_user_t * user) +{ + if (!user) { + return; + } + + if (user->name) { + free(user->name); + } + if (user->client_certificate_data) { + free(user->client_certificate_data); + } + if (user->client_key_data) { + free(user->client_key_data); + } + if (user->username) { + free(user->username); + } + if (user->password) { + free(user->password); + } + if (user->auth_provider) { + kubeconfig_auth_provider_free(user->auth_provider); + } + if (user->exec) { + kubeconfig_exec_free(user->exec); + } + + free(user); +} + +kubeconfig_user_t **kubeconfig_users_create(int users_count) +{ + kubeconfig_user_t **users = (kubeconfig_user_t **) calloc(users_count, sizeof(kubeconfig_user_t *)); + int i = 0; + for (i = 0; i < users_count; i++) { + users[i] = kubeconfig_user_create(); + } + return users; +} + +void kubeconfig_users_free(kubeconfig_user_t ** users, int users_count) +{ + if (!users) { + return; + } + + int i = 0; + for (i = 0; i < users_count; i++) { + if (users[i]) { + kubeconfig_user_free(users[i]); + users[i] = NULL; + } + } + free(users); +} + +kubeconfig_context_t *kubeconfig_context_create() +{ + kubeconfig_context_t *context = calloc(1, sizeof(kubeconfig_context_t)); + return context; +} + +void kubeconfig_context_free(kubeconfig_context_t * context) +{ + if (!context) { + return; + } + + if (context->name) { + free(context->name); + } + if (context->cluster) { + free(context->cluster); + } + if (context->user) { + free(context->user); + } + + free(context); +} + +kubeconfig_context_t **kubeconfig_contexts_create(int contexts_count) +{ + kubeconfig_context_t **contexts = (kubeconfig_context_t **) calloc(contexts_count, sizeof(kubeconfig_context_t *)); + int i = 0; + for (i = 0; i < contexts_count; i++) { + contexts[i] = kubeconfig_context_create(); + } + return contexts; +} + +void kubeconfig_contexts_free(kubeconfig_context_t ** contexts, int context_count) +{ + if (!contexts) { + return; + } + + int i = 0; + for (i = 0; i < context_count; i++) { + if (contexts[i]) { + kubeconfig_context_free(contexts[i]); + contexts[i] = NULL; + } + } + free(contexts); +} + +kubeconfig_t *kubeconfig_create() +{ + kubeconfig_t *config = calloc(1, sizeof(kubeconfig_t)); + return config; +} + +void kubeconfig_free(kubeconfig_t * kubeconfig) +{ + if (!kubeconfig) { + return; + } + + if (kubeconfig->fileName) { + free(kubeconfig->fileName); + } + if (kubeconfig->apiVersion) { + free(kubeconfig->apiVersion); + } + if (kubeconfig->kind) { + free(kubeconfig->kind); + } + if (kubeconfig->preferences) { + free(kubeconfig->preferences); + } + if (kubeconfig->current_context) { + free(kubeconfig->current_context); + } + if (kubeconfig->clusters) { + kubeconfig_clusters_free(kubeconfig->clusters, kubeconfig->clusters_count); + } + if (kubeconfig->users) { + kubeconfig_users_free(kubeconfig->users, kubeconfig->users_count); + } + if (kubeconfig->contexts) { + kubeconfig_contexts_free(kubeconfig->contexts, kubeconfig->contexts_count); + } + + free(kubeconfig); + +} diff --git a/kubernetes/config/kube_config_model.h b/kubernetes/config/kube_config_model.h new file mode 100644 index 0000000..1c3692a --- /dev/null +++ b/kubernetes/config/kube_config_model.h @@ -0,0 +1,89 @@ +#ifndef _KUBE_CONFIG_MODEL_H +#define _KUBE_CONFIG_MODEL_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct kubeconfig_cluster_t { + char *name; + char *server; + char *certificate_authority_data; +} kubeconfig_cluster_t ; + +typedef struct kubeconfig_auth_provider_t { + char *name; + char *id_token; + char *cmd_path; + char *access_token; + char *expires_on; + char *expiry; + char *idp_certificate_authority_data; +} kubeconfig_auth_provider_t ; + +typedef struct kubeconfig_exec_t { + char *command; +} kubeconfig_exec_t; + +typedef struct kubeconfig_user_t { + char *name; + char *client_certificate_data; + char *client_key_data; + kubeconfig_auth_provider_t *auth_provider; + kubeconfig_exec_t *exec; + int insecure_skip_tls_verify; + char *username; + char *password; +} kubeconfig_user_t; + +typedef struct kubeconfig_context_t { + char *name; + char *cluster; + char *user; +} kubeconfig_context_t ; + +typedef struct kubeconfig_t { + char *fileName; + char *apiVersion; + char *preferences; + char *kind; + char *current_context; + kubeconfig_context_t **contexts; + int contexts_count; + kubeconfig_cluster_t **clusters; + int clusters_count; + kubeconfig_user_t **users; + int users_count; +} kubeconfig_t; + + +kubeconfig_auth_provider_t * kubeconfig_auth_provider_create(); +void kubeconfig_auth_provider_free(kubeconfig_auth_provider_t *provider); + +kubeconfig_exec_t * kubeconfig_exec_create(); +void kubeconfig_exec_free(kubeconfig_exec_t *exec); + +kubeconfig_cluster_t * kubeconfig_cluster_create(); +void kubeconfig_cluster_free(kubeconfig_cluster_t *cluster); +kubeconfig_cluster_t ** kubeconfig_clusters_create(int clusters_count); +void kubeconfig_clusters_free(kubeconfig_cluster_t **clusters, int clusters_count); + +kubeconfig_user_t * kubeconfig_user_create(); +void kubeconfig_user_free(kubeconfig_user_t *user); +kubeconfig_user_t ** kubeconfig_users_create(int users_count); +void kubeconfig_users_free(kubeconfig_user_t **users, int users_count); + +kubeconfig_context_t * kubeconfig_context_create(); +void kubeconfig_context_free(kubeconfig_context_t *context); +kubeconfig_context_t ** kubeconfig_contexts_create(int contexts_count); +void kubeconfig_contexts_free(kubeconfig_context_t **contexts, int contexts_count); + +kubeconfig_t * kubeconfig_create(); +void kubeconfig_free(kubeconfig_t *kubeconfig); + +#ifdef __cplusplus +} +#endif + + +#endif /* _KUBE_CONFIG_MODEL_H */ diff --git a/kubernetes/config/kube_config_yaml.c b/kubernetes/config/kube_config_yaml.c new file mode 100644 index 0000000..9af1186 --- /dev/null +++ b/kubernetes/config/kube_config_yaml.c @@ -0,0 +1,407 @@ +#include +#include +#include "kube_config_yaml.h" + +/* +A valid sequence of events should obey the grammar : + +stream :: = STREAM - START document * STREAM - END +document :: = DOCUMENT - START node DOCUMENT - END +node :: = ALIAS | SCALAR | sequence | mapping +sequence :: = SEQUENCE - START node * SEQUENCE - END +mapping :: = MAPPING - START(node node) * MAPPING - END +*/ + +#define KEY_APIVERSION "apiVersion" +#define KEY_KIND "kind" +#define KEY_CURRENT_CONTEXT "current-context" +#define KEY_CLUSTERS "clusters" +#define KEY_CLUSTER "cluster" +#define KEY_CONTEXTS "contexts" +#define KEY_USERS "users" +#define KEY_USER "user" +#define KEY_NAME "name" +#define KEY_CERTIFICATE_AUTHORITY_DATA "certificate-authority-data" +#define KEY_SERVER "server" +#define KEY_CLIENT_CERTIFICATE_DATA "client-certificate-data" +#define KEY_CLIENT_KEY_DATA "client-key-data" + +static int parse_kubeconfig_yaml_userinfo_mapping(kubeconfig_user_t * user, yaml_document_t * document, yaml_node_t * node) +{ + static char fname[] = "parse_kubeconfig_yaml_userinfo_mapping()"; + + yaml_node_pair_t *pair = NULL; + yaml_node_t *key = NULL; + yaml_node_t *value = NULL; + + for (pair = node->data.mapping.pairs.start; pair < node->data.mapping.pairs.top; pair++) { + key = yaml_document_get_node(document, pair->key); + value = yaml_document_get_node(document, pair->value); + + if (key->type != YAML_SCALAR_NODE) { + fprintf(stderr, "%s: The key node is not YAML_SCALAR_NODE.\n", fname); + return -1; + } + + if (value->type == YAML_SCALAR_NODE) { + if (0 == strcmp(key->data.scalar.value, KEY_CLIENT_CERTIFICATE_DATA)) { + user->client_certificate_data = strdup(value->data.scalar.value); + } else if (0 == strcmp(key->data.scalar.value, KEY_CLIENT_KEY_DATA)) { + user->client_key_data = strdup(value->data.scalar.value); + } + } + } + + return 0; +} + +static int parse_kubeconfig_yaml_user_mapping(kubeconfig_user_t * user, yaml_document_t * document, yaml_node_t * node) +{ + static char fname[] = "parse_kubeconfig_yaml_user_mapping()"; + int rc = 0; + + yaml_node_pair_t *pair = NULL; + yaml_node_t *key = NULL; + yaml_node_t *value = NULL; + + for (pair = node->data.mapping.pairs.start; pair < node->data.mapping.pairs.top; pair++) { + key = yaml_document_get_node(document, pair->key); + value = yaml_document_get_node(document, pair->value); + + if (key->type != YAML_SCALAR_NODE) { + fprintf(stderr, "%s: The key node is not YAML_SCALAR_NODE.\n", fname); + return -1; + } + + if (value->type == YAML_SCALAR_NODE) { + if (0 == strcmp(key->data.scalar.value, KEY_NAME)) { + user->name = strdup(value->data.scalar.value); + } + } else if (value->type == YAML_MAPPING_NODE) { + rc = parse_kubeconfig_yaml_userinfo_mapping(user, document, value); + } + } + + return rc; +} + +static int parse_kubeconfig_yaml_users_sequence(kubeconfig_t * kubeconfig, yaml_document_t * document, yaml_node_t * node) +{ + int rc = 0; + + yaml_node_item_t *item = NULL; + yaml_node_t *value = NULL; + int item_count = 0; + int i = 0; + + // Get the count of users + for (item = node->data.sequence.items.start, item_count = 0; item < node->data.sequence.items.top; item++, item_count++) { + ; + } + + kubeconfig->users_count = item_count; + kubeconfig->users = kubeconfig_users_create(kubeconfig->users_count); + + for (item = node->data.sequence.items.start, i = 0; item < node->data.sequence.items.top; item++, i++) { + value = yaml_document_get_node(document, *item); + rc = parse_kubeconfig_yaml_user_mapping(kubeconfig->users[i], document, value); + } + + return rc; + +} + +static int parse_kubeconfig_yaml_contextinfo_mapping(kubeconfig_context_t * context, yaml_document_t * document, yaml_node_t * node) +{ + static char fname[] = "parse_kubeconfig_yaml_contextinfo_mapping()"; + + yaml_node_pair_t *pair = NULL; + yaml_node_t *key = NULL; + yaml_node_t *value = NULL; + + for (pair = node->data.mapping.pairs.start; pair < node->data.mapping.pairs.top; pair++) { + key = yaml_document_get_node(document, pair->key); + value = yaml_document_get_node(document, pair->value); + + if (key->type != YAML_SCALAR_NODE) { + fprintf(stderr, "%s: The key node is not YAML_SCALAR_NODE.\n", fname); + return -1; + } + + if (value->type == YAML_SCALAR_NODE) { + if (0 == strcmp(key->data.scalar.value, KEY_CLUSTER)) { + context->cluster = strdup(value->data.scalar.value); + } else if (0 == strcmp(key->data.scalar.value, KEY_USER)) { + context->user = strdup(value->data.scalar.value); + } + } + } + + return 0; +} + +static int parse_kubeconfig_yaml_context_mapping(kubeconfig_context_t * context, yaml_document_t * document, yaml_node_t * node) +{ + static char fname[] = "parse_kubeconfig_yaml_context_mapping()"; + int rc = 0; + + yaml_node_pair_t *pair = NULL; + yaml_node_t *key = NULL; + yaml_node_t *value = NULL; + + for (pair = node->data.mapping.pairs.start; pair < node->data.mapping.pairs.top; pair++) { + key = yaml_document_get_node(document, pair->key); + value = yaml_document_get_node(document, pair->value); + + if (key->type != YAML_SCALAR_NODE) { + fprintf(stderr, "%s: The key node is not YAML_SCALAR_NODE.\n", fname); + return -1; + } + + if (value->type == YAML_SCALAR_NODE) { + if (0 == strcmp(key->data.scalar.value, KEY_NAME)) { + context->name = strdup(value->data.scalar.value); + } + } else if (value->type == YAML_MAPPING_NODE) { + rc = parse_kubeconfig_yaml_contextinfo_mapping(context, document, value); + } + } + + return rc; +} + +static int parse_kubeconfig_yaml_contexts_sequence(kubeconfig_t * kubeconfig, yaml_document_t * document, yaml_node_t * node) +{ + int rc = 0; + yaml_node_item_t *item = NULL; + yaml_node_t *value = NULL; + int item_count = 0; + int i = 0; + + // Get the count of contexts + for (item = node->data.sequence.items.start, item_count = 0; item < node->data.sequence.items.top; item++, item_count++) { + ; + } + + kubeconfig->contexts_count = item_count; + kubeconfig->contexts = kubeconfig_contexts_create(kubeconfig->contexts_count); + + for (item = node->data.sequence.items.start, i = 0; item < node->data.sequence.items.top; item++, i++) { + value = yaml_document_get_node(document, *item); + rc = parse_kubeconfig_yaml_context_mapping(kubeconfig->contexts[i], document, value); + } + + return rc; + +} + +static int parse_kubeconfig_yaml_clusterinfo_mapping(kubeconfig_cluster_t * cluster, yaml_document_t * document, yaml_node_t * node) +{ + static char fname[] = "parse_kubeconfig_yaml_clusterinfo_mapping()"; + + yaml_node_pair_t *pair = NULL; + yaml_node_t *key = NULL; + yaml_node_t *value = NULL; + + for (pair = node->data.mapping.pairs.start; pair < node->data.mapping.pairs.top; pair++) { + key = yaml_document_get_node(document, pair->key); + value = yaml_document_get_node(document, pair->value); + + if (key->type != YAML_SCALAR_NODE) { + fprintf(stderr, "%s: The key node is not YAML_SCALAR_NODE.\n", fname); + return -1; + } + + if (value->type == YAML_SCALAR_NODE) { + if (0 == strcmp(key->data.scalar.value, KEY_CERTIFICATE_AUTHORITY_DATA)) { + cluster->certificate_authority_data = strdup(value->data.scalar.value); + } else if (0 == strcmp(key->data.scalar.value, KEY_SERVER)) { + cluster->server = strdup(value->data.scalar.value); + } + } + } + + return 0; +} + +static int parse_kubeconfig_yaml_cluster_mapping(kubeconfig_cluster_t * cluster, yaml_document_t * document, yaml_node_t * node) +{ + static char fname[] = "parse_kubeconfig_yaml_cluster_mapping()"; + int rc = 0; + + yaml_node_pair_t *pair = NULL; + yaml_node_t *key = NULL; + yaml_node_t *value = NULL; + + for (pair = node->data.mapping.pairs.start; pair < node->data.mapping.pairs.top; pair++) { + key = yaml_document_get_node(document, pair->key); + value = yaml_document_get_node(document, pair->value); + + if (key->type != YAML_SCALAR_NODE) { + fprintf(stderr, "%s: The key node is not YAML_SCALAR_NODE.\n", fname); + return -1; + } + + if (value->type == YAML_SCALAR_NODE) { + if (0 == strcmp(key->data.scalar.value, KEY_NAME)) { + cluster->name = strdup(value->data.scalar.value); + } + } else if (value->type == YAML_MAPPING_NODE) { + rc = parse_kubeconfig_yaml_clusterinfo_mapping(cluster, document, value); + } + } + + return rc; +} + +static int parse_kubeconfig_yaml_clusters_sequence(kubeconfig_t * kubeconfig, yaml_document_t * document, yaml_node_t * node) +{ + int rc = 0; + yaml_node_item_t *item = NULL; + yaml_node_t *value = NULL; + int item_count = 0; + int i = 0; + + // Get the count of clusters + for (item = node->data.sequence.items.start, item_count = 0; item < node->data.sequence.items.top; item++, item_count++) { + ; + } + + kubeconfig->clusters_count = item_count; + kubeconfig->clusters = kubeconfig_clusters_create(kubeconfig->clusters_count); + + for (item = node->data.sequence.items.start, i = 0; item < node->data.sequence.items.top; item++, i++) { + value = yaml_document_get_node(document, *item); + rc = parse_kubeconfig_yaml_cluster_mapping(kubeconfig->clusters[i], document, value); + } + + return rc; + +} + +static int parse_kubeconfig_yaml_top_mapping(kubeconfig_t * kubeconfig, yaml_document_t * document, yaml_node_t * node) +{ + static char fname[] = "parse_kubeconfig_yaml_top_mapping()"; + int rc = 0; + + yaml_node_pair_t *pair = NULL; + yaml_node_t *key = NULL; + yaml_node_t *value = NULL; + + for (pair = node->data.mapping.pairs.start; pair < node->data.mapping.pairs.top; pair++) { + key = yaml_document_get_node(document, pair->key); + value = yaml_document_get_node(document, pair->value); + + if (key->type != YAML_SCALAR_NODE) { + fprintf(stderr, "%s: The key node is not YAML_SCALAR_NODE.\n", fname); + return -1; + } + + if (value->type == YAML_SCALAR_NODE) { + if (0 == strcmp(key->data.scalar.value, KEY_APIVERSION)) { + kubeconfig->apiVersion = strdup(value->data.scalar.value); + } else if (0 == strcmp(key->data.scalar.value, KEY_KIND)) { + kubeconfig->kind = strdup(value->data.scalar.value); + } else if (0 == strcmp(key->data.scalar.value, KEY_CURRENT_CONTEXT)) { + kubeconfig->current_context = strdup(value->data.scalar.value); + } + } else { + if (0 == strcmp(key->data.scalar.value, KEY_CLUSTERS)) { + rc = parse_kubeconfig_yaml_clusters_sequence(kubeconfig, document, value); + } else if (0 == strcmp(key->data.scalar.value, KEY_CONTEXTS)) { + rc = parse_kubeconfig_yaml_contexts_sequence(kubeconfig, document, value); + } else if (0 == strcmp(key->data.scalar.value, KEY_USERS)) { + rc = parse_kubeconfig_yaml_users_sequence(kubeconfig, document, value); + } + } + } + + return rc; + +} + +static int parse_kubeconfig_yaml_node(kubeconfig_t * kubeconfig, yaml_document_t * document, yaml_node_t * node) +{ + static char fname[] = "parse_kubeconfig_yaml_node()"; + int rc = 0; + + if (YAML_MAPPING_NODE == node->type) { + rc = parse_kubeconfig_yaml_top_mapping(kubeconfig, document, node); + } else { + fprintf(stderr, "%s: %s is not a valid kubeconfig file.\n", fname, kubeconfig->fileName); + rc = -1; + } + + return rc; +} + +static int parse_kubeconfig_yaml_document(kubeconfig_t * kubeconfig, yaml_document_t * document) +{ + static char fname[] = "parse_kubeconfig_yaml_document()"; + int rc = 0; + + yaml_node_t *root; + root = yaml_document_get_root_node(document); + if (NULL == root) { + fprintf(stderr, "%s: The document is null\n", fname); + return -1; + } + + rc = parse_kubeconfig_yaml_node(kubeconfig, document, root); + + return rc; +} + +int kubeyaml_load_kubeconfig(kubeconfig_t * kubeconfig) +{ + static char fname[] = "kubeyaml_load_kubeconfig()"; + + yaml_parser_t parser; + yaml_document_t document; + + int done = 0; + + /* Create the Parser object. */ + yaml_parser_initialize(&parser); + + /* Set a file input. */ + FILE *input = NULL; + if (kubeconfig->fileName) { + input = fopen(kubeconfig->fileName, "rb"); + if (!input) { + fprintf(stderr, "%s: Cannot open the file %s.[%s]\n", fname, kubeconfig->fileName, strerror(errno)); + return -1; + } + } else { + fprintf(stderr, "%s: The kubeconf file name needs be set by kubeconfig->fileName .\n", fname); + return -1; + } + + yaml_parser_set_input_file(&parser, input); + + while (!done) { + + if (!yaml_parser_load(&parser, &document)) { + goto error; + } + + done = (!yaml_document_get_root_node(&document)); + + if (!done) { + parse_kubeconfig_yaml_document(kubeconfig, &document); + } + + yaml_document_delete(&document); + + } + + /* Cleanup */ + yaml_parser_delete(&parser); + fclose(input); + return 0; + + error: + yaml_parser_delete(&parser); + fclose(input); + return -1; +} diff --git a/kubernetes/config/kube_config_yaml.h b/kubernetes/config/kube_config_yaml.h new file mode 100644 index 0000000..49b62a3 --- /dev/null +++ b/kubernetes/config/kube_config_yaml.h @@ -0,0 +1,37 @@ +#ifndef _KUBE_CONFIG_YAML_H +#define _KUBE_CONFIG_YAML_H + +#include "kube_config_model.h" + +#ifdef __cplusplus +extern "C" { + +#endif /* __cplusplus */ + +/* + * kubeyaml_load_kubeconfig + * + * Description: + * + * Load the kubeconfig file specified by kubeconfig->fileName + * and get the kuberntes configuration for other fields of kubeconfig. + * + * Return: + * + * 0 Success + * -1 Failed + * + * Parameter: + * + * IN: + * kubeconfig->fileName: kubernetes cluster configuration file name + * + * OUT: + * kubeconfig: kubernetes cluster configuration + */ +int kubeyaml_load_kubeconfig(kubeconfig_t * kubeconfig); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _KUBE_CONFIG_YAML_H */ From ed82ac046a90f181d9b1580ddae30f3666e5aeaf Mon Sep 17 00:00:00 2001 From: Hui Yu Date: Tue, 7 Apr 2020 22:44:34 +0800 Subject: [PATCH 2/2] [Configuration]Update the data structures for kube config file --- kubernetes/config/kube_config.c | 95 +++-------- kubernetes/config/kube_config_model.c | 223 ++++++++++--------------- kubernetes/config/kube_config_model.h | 95 +++++------ kubernetes/config/kube_config_yaml.c | 228 +++++--------------------- 4 files changed, 196 insertions(+), 445 deletions(-) diff --git a/kubernetes/config/kube_config.c b/kubernetes/config/kube_config.c index 130a192..95a1ec3 100644 --- a/kubernetes/config/kube_config.c +++ b/kubernetes/config/kube_config.c @@ -2,23 +2,21 @@ #include "kube_config_yaml.h" #include #include +#include -#define ENV_KUBECONFIGE "KUBECONFIG" +#define ENV_KUBECONFIG "KUBECONFIG" #define ENV_HOME "HOME" #define KUBE_CONFIG_DEFAULT_LOCATION "%s/.kube/config" #define KUBE_CONFIG_TEMPFILE_NAME_TEMPLATE "/tmp/kubeconfig-XXXXXX" static int setBasePath(char **pBasePath, char *basePath) { - int rc = 0; char *_basePath = strdup(basePath); if (_basePath) { *pBasePath = _basePath; - } else { - rc = -1; + return 0; } - return rc; - + return -1; } static char *kubeconfig_mk_cert_key_tempfile(const char *b64data) @@ -39,14 +37,13 @@ static char *kubeconfig_mk_cert_key_tempfile(const char *b64data) return NULL; } - if (-1 == write(fd, b64decode, decoded_bytes)) { + int rc = write(fd, b64decode, decoded_bytes); + close(fd); + if (-1 == rc) { fprintf(stderr, "%s: Writing temp file failed with error [%s]\n", fname, strerror(errno)); - close(fd); return NULL; } - close(fd); - return strdup(tempfile_name_template); } @@ -72,10 +69,9 @@ static void unsetSslConfig(sslConfig_t * sslConfig) if (sslConfig->CACertFile) { kubeconfig_rm_tempfile(sslConfig->CACertFile); } - } -static int setSslConfig(sslConfig_t ** pSslConfig, kubeconfig_cluster_t * cluster, kubeconfig_user_t * user) +static int setSslConfig(sslConfig_t ** pSslConfig, const kubeconfig_property_t * cluster, const kubeconfig_property_t * user) { int rc = 0; char *client_cert_file = NULL; @@ -119,19 +115,17 @@ static int setSslConfig(sslConfig_t ** pSslConfig, kubeconfig_cluster_t * cluste return rc; } -static int setApiKeys(list_t ** pApiKeys, kubeconfig_user_t * user) +static int setApiKeys(list_t ** pApiKeys, const kubeconfig_property_t * user) { - int rc = 0; list_t *apiKeys = list_create(); if (apiKeys) { /* under development for the token based authentication */ *pApiKeys = apiKeys; - } else { - rc = -1; + return 0; } - return rc; + return -1; } static char *getWorkingConfigFile(const char *configFileNamePassedIn) @@ -143,7 +137,7 @@ static char *getWorkingConfigFile(const char *configFileNamePassedIn) if (configFileNamePassedIn) { configFileName = strdup(configFileNamePassedIn); } else { - kubeconfig_env = getenv(ENV_KUBECONFIGE); + kubeconfig_env = getenv(ENV_KUBECONFIG); if (kubeconfig_env) { configFileName = strdup(kubeconfig_env); } else { @@ -160,61 +154,22 @@ static char *getWorkingConfigFile(const char *configFileNamePassedIn) return configFileName; } -static kubeconfig_context_t *kubeconfig_get_current_context(kubeconfig_context_t ** contexts, int contexts_count, const char *current_context_str) +static const kubeconfig_property_t *kubeconfig_get_current_property(kubeconfig_property_t ** properties, int properties_count, const char *property_name) { - kubeconfig_context_t *current_context = NULL; + const kubeconfig_property_t *current_property = NULL; - if (NULL == contexts || NULL == current_context_str) { + if (NULL == properties || NULL == property_name) { return NULL; } - int i = 0; - for (i = 0; i < contexts_count; i++) { - if (0 == strcmp(contexts[i]->name, current_context_str)) { - current_context = contexts[i]; + for (int i = 0; i < properties_count; i++) { + if (0 == strcmp(properties[i]->name, property_name)) { + current_property = properties[i]; break; } } - return current_context; -} - -static kubeconfig_cluster_t *kubeconfig_get_current_cluster(kubeconfig_cluster_t ** clusters, int clusters_count, const char *cluster_name) -{ - kubeconfig_cluster_t *current_cluster = NULL; - - if (NULL == clusters || NULL == cluster_name) { - return NULL; - } - - int i = 0; - for (i = 0; i < clusters_count; i++) { - if (0 == strcmp(clusters[i]->name, cluster_name)) { - current_cluster = clusters[i]; - break; - } - } - - return current_cluster; -} - -static kubeconfig_user_t *kubeconfig_get_current_user(kubeconfig_user_t ** users, int users_count, const char *user_name) -{ - kubeconfig_user_t *current_user = NULL; - - if (NULL == users || NULL == user_name) { - return NULL; - } - - int i = 0; - for (i = 0; i < users_count; i++) { - if (0 == strcmp(users[i]->name, user_name)) { - current_user = users[i]; - break; - } - } - - return current_user; + return current_property; } int load_kube_config(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApiKeys, const char *configFileName) @@ -223,9 +178,9 @@ int load_kube_config(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApi int rc = 0; - kubeconfig_context_t *current_context = NULL; - kubeconfig_cluster_t *current_cluster = NULL; - kubeconfig_user_t *current_user = NULL; + const kubeconfig_property_t *current_context = NULL; + const kubeconfig_property_t *current_cluster = NULL; + const kubeconfig_property_t *current_user = NULL; kubeconfig_t *kubeconfig = kubeconfig_create(); if (!kubeconfig) { @@ -241,21 +196,21 @@ int load_kube_config(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApi goto end; } - current_context = kubeconfig_get_current_context(kubeconfig->contexts, kubeconfig->contexts_count, kubeconfig->current_context); + current_context = kubeconfig_get_current_property(kubeconfig->contexts, kubeconfig->contexts_count, kubeconfig->current_context); if (!current_context) { fprintf(stderr, "%s: Cannot get the current context by the kubeconfig.\n", fname); rc = -1; goto end; } - current_cluster = kubeconfig_get_current_cluster(kubeconfig->clusters, kubeconfig->clusters_count, current_context->cluster); + current_cluster = kubeconfig_get_current_property(kubeconfig->clusters, kubeconfig->clusters_count, current_context->cluster); if (!current_cluster) { fprintf(stderr, "%s: Cannot get the current cluster information by the kubeconfig.\n", fname); rc = -1; goto end; } - current_user = kubeconfig_get_current_user(kubeconfig->users, kubeconfig->users_count, current_context->user); + current_user = kubeconfig_get_current_property(kubeconfig->users, kubeconfig->users_count, current_context->user); if (!current_user) { fprintf(stderr, "%s: Cannot get the current user information by the kubeconfig.\n", fname); rc = -1; diff --git a/kubernetes/config/kube_config_model.c b/kubernetes/config/kube_config_model.c index 555f00a..9d4518c 100644 --- a/kubernetes/config/kube_config_model.c +++ b/kubernetes/config/kube_config_model.c @@ -15,24 +15,31 @@ void kubeconfig_auth_provider_free(kubeconfig_auth_provider_t * provider) if (provider->name) { free(provider->name); + provider->name = NULL; } if (provider->id_token) { free(provider->id_token); + provider->id_token = NULL; } if (provider->cmd_path) { free(provider->cmd_path); + provider->cmd_path = NULL; } if (provider->access_token) { free(provider->access_token); + provider->access_token = NULL; } if (provider->expires_on) { free(provider->expires_on); + provider->expires_on = NULL; } if (provider->expiry) { free(provider->expiry); + provider->expiry = NULL; } if (provider->idp_certificate_authority_data) { free(provider->idp_certificate_authority_data); + provider->idp_certificate_authority_data = NULL; } free(provider); @@ -52,174 +59,105 @@ void kubeconfig_exec_free(kubeconfig_exec_t * exec) if (exec->command) { free(exec->command); + exec->command = NULL; } free(exec); } -kubeconfig_cluster_t *kubeconfig_cluster_create() +kubeconfig_property_t *kubeconfig_property_create(kubeconfig_property_type_t type) { - kubeconfig_cluster_t *cluster = calloc(1, sizeof(kubeconfig_cluster_t)); - return cluster; + kubeconfig_property_t *property = calloc(1, sizeof(kubeconfig_property_t)); + property->type = type; + return property; } -void kubeconfig_cluster_free(kubeconfig_cluster_t * cluster) +void kubeconfig_property_free(kubeconfig_property_t * property) { - if (!cluster) { + if (!property) { return; } - if (cluster->name) { - free(cluster->name); - } - if (cluster->server) { - free(cluster->server); - } - if (cluster->certificate_authority_data) { - free(cluster->certificate_authority_data); + if (property->name) { + free(property->name); + property->name = NULL; } - free(cluster); -} - -kubeconfig_cluster_t **kubeconfig_clusters_create(int clusters_count) -{ - kubeconfig_cluster_t **clusters = (kubeconfig_cluster_t **) calloc(clusters_count, sizeof(kubeconfig_cluster_t *)); - int i = 0; - for (i = 0; i < clusters_count; i++) { - clusters[i] = kubeconfig_cluster_create(); - } - return clusters; -} - -void kubeconfig_clusters_free(kubeconfig_cluster_t ** clusters, int cluster_count) -{ - if (!clusters) { - return; - } - - int i = 0; - for (i = 0; i < cluster_count; i++) { - if (clusters[i]) { - kubeconfig_cluster_free(clusters[i]); - clusters[i] = NULL; + if (KUBECONFIG_PROPERTY_TYPE_CLUSTER == property->type) { + if (property->server) { + free(property->server); + property->server = NULL; + } + if (property->certificate_authority_data) { + free(property->certificate_authority_data); + property->certificate_authority_data = NULL; } } - free(clusters); -} -kubeconfig_user_t *kubeconfig_user_create() -{ - kubeconfig_user_t *user = calloc(1, sizeof(kubeconfig_user_t)); - return user; -} - -void kubeconfig_user_free(kubeconfig_user_t * user) -{ - if (!user) { - return; - } - - if (user->name) { - free(user->name); - } - if (user->client_certificate_data) { - free(user->client_certificate_data); - } - if (user->client_key_data) { - free(user->client_key_data); - } - if (user->username) { - free(user->username); - } - if (user->password) { - free(user->password); - } - if (user->auth_provider) { - kubeconfig_auth_provider_free(user->auth_provider); - } - if (user->exec) { - kubeconfig_exec_free(user->exec); - } - - free(user); -} - -kubeconfig_user_t **kubeconfig_users_create(int users_count) -{ - kubeconfig_user_t **users = (kubeconfig_user_t **) calloc(users_count, sizeof(kubeconfig_user_t *)); - int i = 0; - for (i = 0; i < users_count; i++) { - users[i] = kubeconfig_user_create(); - } - return users; -} - -void kubeconfig_users_free(kubeconfig_user_t ** users, int users_count) -{ - if (!users) { - return; - } - - int i = 0; - for (i = 0; i < users_count; i++) { - if (users[i]) { - kubeconfig_user_free(users[i]); - users[i] = NULL; + if (KUBECONFIG_PROPERTY_TYPE_USER == property->type) { + if (property->client_certificate_data) { + free(property->client_certificate_data); + property->client_certificate_data = NULL; + } + if (property->client_key_data) { + free(property->client_key_data); + property->client_key_data = NULL; + } + if (property->username) { + free(property->username); + property->username = NULL; + } + if (property->password) { + free(property->password); + property->password = NULL; + } + if (property->auth_provider) { + kubeconfig_auth_provider_free(property->auth_provider); + property->auth_provider = NULL; + } + if (property->exec) { + kubeconfig_exec_free(property->exec); + property->exec = NULL; } } - free(users); + + if (KUBECONFIG_PROPERTY_TYPE_CONTEXT == property->type) { + if (property->cluster) { + free(property->cluster); + property->cluster = NULL; + } + if (property->user) { + free(property->user); + property->user = NULL; + } + } + + free(property); } -kubeconfig_context_t *kubeconfig_context_create() +kubeconfig_property_t **kubeconfig_properties_create(int contexts_count, kubeconfig_property_type_t type) { - kubeconfig_context_t *context = calloc(1, sizeof(kubeconfig_context_t)); - return context; -} - -void kubeconfig_context_free(kubeconfig_context_t * context) -{ - if (!context) { - return; - } - - if (context->name) { - free(context->name); - } - if (context->cluster) { - free(context->cluster); - } - if (context->user) { - free(context->user); - } - - free(context); -} - -kubeconfig_context_t **kubeconfig_contexts_create(int contexts_count) -{ - kubeconfig_context_t **contexts = (kubeconfig_context_t **) calloc(contexts_count, sizeof(kubeconfig_context_t *)); + kubeconfig_property_t **properties = (kubeconfig_property_t **) calloc(contexts_count, sizeof(kubeconfig_property_t *)); int i = 0; for (i = 0; i < contexts_count; i++) { - contexts[i] = kubeconfig_context_create(); + properties[i] = kubeconfig_property_create(type); } - return contexts; + return properties; } -void kubeconfig_contexts_free(kubeconfig_context_t ** contexts, int context_count) +void kubeconfig_properties_free(kubeconfig_property_t ** properties, int properties_count) { - if (!contexts) { + if (!properties) { return; } - int i = 0; - for (i = 0; i < context_count; i++) { - if (contexts[i]) { - kubeconfig_context_free(contexts[i]); - contexts[i] = NULL; + for (int i = 0; i < properties_count; i++) { + if (properties[i]) { + kubeconfig_property_free(properties[i]); + properties[i] = NULL; } } - free(contexts); + free(properties); } kubeconfig_t *kubeconfig_create() @@ -236,29 +174,36 @@ void kubeconfig_free(kubeconfig_t * kubeconfig) if (kubeconfig->fileName) { free(kubeconfig->fileName); + kubeconfig->fileName = NULL; } if (kubeconfig->apiVersion) { free(kubeconfig->apiVersion); + kubeconfig->apiVersion = NULL; } if (kubeconfig->kind) { free(kubeconfig->kind); + kubeconfig->kind = NULL; } if (kubeconfig->preferences) { free(kubeconfig->preferences); + kubeconfig->preferences = NULL; } if (kubeconfig->current_context) { free(kubeconfig->current_context); + kubeconfig->current_context = NULL; } if (kubeconfig->clusters) { - kubeconfig_clusters_free(kubeconfig->clusters, kubeconfig->clusters_count); + kubeconfig_properties_free(kubeconfig->clusters, kubeconfig->clusters_count); + kubeconfig->clusters = NULL; } if (kubeconfig->users) { - kubeconfig_users_free(kubeconfig->users, kubeconfig->users_count); + kubeconfig_properties_free(kubeconfig->users, kubeconfig->users_count); + kubeconfig->users = NULL; } if (kubeconfig->contexts) { - kubeconfig_contexts_free(kubeconfig->contexts, kubeconfig->contexts_count); + kubeconfig_properties_free(kubeconfig->contexts, kubeconfig->contexts_count); + kubeconfig->contexts = NULL; } free(kubeconfig); - } diff --git a/kubernetes/config/kube_config_model.h b/kubernetes/config/kube_config_model.h index 1c3692a..bdbcc7e 100644 --- a/kubernetes/config/kube_config_model.h +++ b/kubernetes/config/kube_config_model.h @@ -5,12 +5,6 @@ extern "C" { #endif -typedef struct kubeconfig_cluster_t { - char *name; - char *server; - char *certificate_authority_data; -} kubeconfig_cluster_t ; - typedef struct kubeconfig_auth_provider_t { char *name; char *id_token; @@ -19,28 +13,41 @@ typedef struct kubeconfig_auth_provider_t { char *expires_on; char *expiry; char *idp_certificate_authority_data; -} kubeconfig_auth_provider_t ; +} kubeconfig_auth_provider_t; typedef struct kubeconfig_exec_t { char *command; } kubeconfig_exec_t; -typedef struct kubeconfig_user_t { - char *name; - char *client_certificate_data; - char *client_key_data; - kubeconfig_auth_provider_t *auth_provider; - kubeconfig_exec_t *exec; - int insecure_skip_tls_verify; - char *username; - char *password; -} kubeconfig_user_t; +typedef enum kubeconfig_property_type_t { + KUBECONFIG_PROPERTY_TYPE_CONTEXT = 1, + KUBECONFIG_PROPERTY_TYPE_CLUSTER, + KUBECONFIG_PROPERTY_TYPE_USER +} kubeconfig_property_type_t; -typedef struct kubeconfig_context_t { +typedef struct kubeconfig_property_t { + kubeconfig_property_type_t type; char *name; - char *cluster; - char *user; -} kubeconfig_context_t ; + union { + struct { /* context */ + char *cluster; + char *user; + }; + struct { /* cluster */ + char *server; + char *certificate_authority_data; + }; + struct { /* user */ + char *client_certificate_data; + char *client_key_data; + kubeconfig_auth_provider_t *auth_provider; + kubeconfig_exec_t *exec; + int insecure_skip_tls_verify; + char *username; + char *password; + }; + }; +} kubeconfig_property_t; typedef struct kubeconfig_t { char *fileName; @@ -48,42 +55,30 @@ typedef struct kubeconfig_t { char *preferences; char *kind; char *current_context; - kubeconfig_context_t **contexts; - int contexts_count; - kubeconfig_cluster_t **clusters; - int clusters_count; - kubeconfig_user_t **users; - int users_count; + kubeconfig_property_t **contexts; + int contexts_count; + kubeconfig_property_t **clusters; + int clusters_count; + kubeconfig_property_t **users; + int users_count; } kubeconfig_t; +kubeconfig_auth_provider_t *kubeconfig_auth_provider_create(); +void kubeconfig_auth_provider_free(kubeconfig_auth_provider_t * provider); -kubeconfig_auth_provider_t * kubeconfig_auth_provider_create(); -void kubeconfig_auth_provider_free(kubeconfig_auth_provider_t *provider); +kubeconfig_exec_t *kubeconfig_exec_create(); +void kubeconfig_exec_free(kubeconfig_exec_t * exec); -kubeconfig_exec_t * kubeconfig_exec_create(); -void kubeconfig_exec_free(kubeconfig_exec_t *exec); +kubeconfig_property_t *kubeconfig_property_create(kubeconfig_property_type_t type); +void kubeconfig_property_free(kubeconfig_property_t * property); -kubeconfig_cluster_t * kubeconfig_cluster_create(); -void kubeconfig_cluster_free(kubeconfig_cluster_t *cluster); -kubeconfig_cluster_t ** kubeconfig_clusters_create(int clusters_count); -void kubeconfig_clusters_free(kubeconfig_cluster_t **clusters, int clusters_count); +kubeconfig_property_t **kubeconfig_properties_create(int contexts_count, kubeconfig_property_type_t type); +void kubeconfig_properties_free(kubeconfig_property_t ** properties, int properties_count); -kubeconfig_user_t * kubeconfig_user_create(); -void kubeconfig_user_free(kubeconfig_user_t *user); -kubeconfig_user_t ** kubeconfig_users_create(int users_count); -void kubeconfig_users_free(kubeconfig_user_t **users, int users_count); - -kubeconfig_context_t * kubeconfig_context_create(); -void kubeconfig_context_free(kubeconfig_context_t *context); -kubeconfig_context_t ** kubeconfig_contexts_create(int contexts_count); -void kubeconfig_contexts_free(kubeconfig_context_t **contexts, int contexts_count); - -kubeconfig_t * kubeconfig_create(); -void kubeconfig_free(kubeconfig_t *kubeconfig); +kubeconfig_t *kubeconfig_create(); +void kubeconfig_free(kubeconfig_t * kubeconfig); #ifdef __cplusplus } #endif - - -#endif /* _KUBE_CONFIG_MODEL_H */ +#endif /* _KUBE_CONFIG_MODEL_H */ diff --git a/kubernetes/config/kube_config_yaml.c b/kubernetes/config/kube_config_yaml.c index 9af1186..1ce1097 100644 --- a/kubernetes/config/kube_config_yaml.c +++ b/kubernetes/config/kube_config_yaml.c @@ -26,9 +26,9 @@ mapping :: = MAPPING - START(node node) * MAPPING - END #define KEY_CLIENT_CERTIFICATE_DATA "client-certificate-data" #define KEY_CLIENT_KEY_DATA "client-key-data" -static int parse_kubeconfig_yaml_userinfo_mapping(kubeconfig_user_t * user, yaml_document_t * document, yaml_node_t * node) +static int parse_kubeconfig_yaml_property_info_mapping(kubeconfig_property_t * property, yaml_document_t * document, yaml_node_t * node) { - static char fname[] = "parse_kubeconfig_yaml_userinfo_mapping()"; + static char fname[] = "parse_kubeconfig_yaml_property_info_mapping()"; yaml_node_pair_t *pair = NULL; yaml_node_t *key = NULL; @@ -44,10 +44,24 @@ static int parse_kubeconfig_yaml_userinfo_mapping(kubeconfig_user_t * user, yaml } if (value->type == YAML_SCALAR_NODE) { - if (0 == strcmp(key->data.scalar.value, KEY_CLIENT_CERTIFICATE_DATA)) { - user->client_certificate_data = strdup(value->data.scalar.value); - } else if (0 == strcmp(key->data.scalar.value, KEY_CLIENT_KEY_DATA)) { - user->client_key_data = strdup(value->data.scalar.value); + if (KUBECONFIG_PROPERTY_TYPE_CLUSTER == property->type) { + if (0 == strcmp(key->data.scalar.value, KEY_CERTIFICATE_AUTHORITY_DATA)) { + property->certificate_authority_data = strdup(value->data.scalar.value); + } else if (0 == strcmp(key->data.scalar.value, KEY_SERVER)) { + property->server = strdup(value->data.scalar.value); + } + } else if (KUBECONFIG_PROPERTY_TYPE_USER == property->type) { + if (0 == strcmp(key->data.scalar.value, KEY_CLIENT_CERTIFICATE_DATA)) { + property->client_certificate_data = strdup(value->data.scalar.value); + } else if (0 == strcmp(key->data.scalar.value, KEY_CLIENT_KEY_DATA)) { + property->client_key_data = strdup(value->data.scalar.value); + } + } else if (KUBECONFIG_PROPERTY_TYPE_CONTEXT == property->type) { + if (0 == strcmp(key->data.scalar.value, KEY_CLUSTER)) { + property->cluster = strdup(value->data.scalar.value); + } else if (0 == strcmp(key->data.scalar.value, KEY_USER)) { + property->user = strdup(value->data.scalar.value); + } } } } @@ -55,9 +69,9 @@ static int parse_kubeconfig_yaml_userinfo_mapping(kubeconfig_user_t * user, yaml return 0; } -static int parse_kubeconfig_yaml_user_mapping(kubeconfig_user_t * user, yaml_document_t * document, yaml_node_t * node) +static int parse_kubeconfig_yaml_property_mapping(kubeconfig_property_t * property, yaml_document_t * document, yaml_node_t * node) { - static char fname[] = "parse_kubeconfig_yaml_user_mapping()"; + static char fname[] = "parse_kubeconfig_yaml_property_mapping()"; int rc = 0; yaml_node_pair_t *pair = NULL; @@ -75,207 +89,49 @@ static int parse_kubeconfig_yaml_user_mapping(kubeconfig_user_t * user, yaml_doc if (value->type == YAML_SCALAR_NODE) { if (0 == strcmp(key->data.scalar.value, KEY_NAME)) { - user->name = strdup(value->data.scalar.value); + property->name = strdup(value->data.scalar.value); } } else if (value->type == YAML_MAPPING_NODE) { - rc = parse_kubeconfig_yaml_userinfo_mapping(user, document, value); + rc = parse_kubeconfig_yaml_property_info_mapping(property, document, value); } } return rc; } -static int parse_kubeconfig_yaml_users_sequence(kubeconfig_t * kubeconfig, yaml_document_t * document, yaml_node_t * node) +static int parse_kubeconfig_yaml_sequence(kubeconfig_property_t *** p_properties, int *p_properties_count, kubeconfig_property_type_t type, yaml_document_t * document, yaml_node_t * node) { - int rc = 0; - yaml_node_item_t *item = NULL; yaml_node_t *value = NULL; int item_count = 0; int i = 0; + int rc = 0; - // Get the count of users + // Get the count of data (e.g. cluster, context, user) for (item = node->data.sequence.items.start, item_count = 0; item < node->data.sequence.items.top; item++, item_count++) { ; } - kubeconfig->users_count = item_count; - kubeconfig->users = kubeconfig_users_create(kubeconfig->users_count); + int properties_count = item_count; + kubeconfig_property_t **properties = kubeconfig_properties_create(properties_count, type); + if (!properties) { + fprintf(stderr, "Cannot allocate memory for kubeconfig properties.\n"); + return -1; + } for (item = node->data.sequence.items.start, i = 0; item < node->data.sequence.items.top; item++, i++) { value = yaml_document_get_node(document, *item); - rc = parse_kubeconfig_yaml_user_mapping(kubeconfig->users[i], document, value); - } - - return rc; - -} - -static int parse_kubeconfig_yaml_contextinfo_mapping(kubeconfig_context_t * context, yaml_document_t * document, yaml_node_t * node) -{ - static char fname[] = "parse_kubeconfig_yaml_contextinfo_mapping()"; - - yaml_node_pair_t *pair = NULL; - yaml_node_t *key = NULL; - yaml_node_t *value = NULL; - - for (pair = node->data.mapping.pairs.start; pair < node->data.mapping.pairs.top; pair++) { - key = yaml_document_get_node(document, pair->key); - value = yaml_document_get_node(document, pair->value); - - if (key->type != YAML_SCALAR_NODE) { - fprintf(stderr, "%s: The key node is not YAML_SCALAR_NODE.\n", fname); + rc = parse_kubeconfig_yaml_property_mapping(properties[i], document, value); + if (0 != rc) { + fprintf(stderr, "Cannot parse kubeconfi properties.\n"); return -1; } - - if (value->type == YAML_SCALAR_NODE) { - if (0 == strcmp(key->data.scalar.value, KEY_CLUSTER)) { - context->cluster = strdup(value->data.scalar.value); - } else if (0 == strcmp(key->data.scalar.value, KEY_USER)) { - context->user = strdup(value->data.scalar.value); - } - } } + *p_properties = properties; + *p_properties_count = properties_count; + return 0; -} - -static int parse_kubeconfig_yaml_context_mapping(kubeconfig_context_t * context, yaml_document_t * document, yaml_node_t * node) -{ - static char fname[] = "parse_kubeconfig_yaml_context_mapping()"; - int rc = 0; - - yaml_node_pair_t *pair = NULL; - yaml_node_t *key = NULL; - yaml_node_t *value = NULL; - - for (pair = node->data.mapping.pairs.start; pair < node->data.mapping.pairs.top; pair++) { - key = yaml_document_get_node(document, pair->key); - value = yaml_document_get_node(document, pair->value); - - if (key->type != YAML_SCALAR_NODE) { - fprintf(stderr, "%s: The key node is not YAML_SCALAR_NODE.\n", fname); - return -1; - } - - if (value->type == YAML_SCALAR_NODE) { - if (0 == strcmp(key->data.scalar.value, KEY_NAME)) { - context->name = strdup(value->data.scalar.value); - } - } else if (value->type == YAML_MAPPING_NODE) { - rc = parse_kubeconfig_yaml_contextinfo_mapping(context, document, value); - } - } - - return rc; -} - -static int parse_kubeconfig_yaml_contexts_sequence(kubeconfig_t * kubeconfig, yaml_document_t * document, yaml_node_t * node) -{ - int rc = 0; - yaml_node_item_t *item = NULL; - yaml_node_t *value = NULL; - int item_count = 0; - int i = 0; - - // Get the count of contexts - for (item = node->data.sequence.items.start, item_count = 0; item < node->data.sequence.items.top; item++, item_count++) { - ; - } - - kubeconfig->contexts_count = item_count; - kubeconfig->contexts = kubeconfig_contexts_create(kubeconfig->contexts_count); - - for (item = node->data.sequence.items.start, i = 0; item < node->data.sequence.items.top; item++, i++) { - value = yaml_document_get_node(document, *item); - rc = parse_kubeconfig_yaml_context_mapping(kubeconfig->contexts[i], document, value); - } - - return rc; - -} - -static int parse_kubeconfig_yaml_clusterinfo_mapping(kubeconfig_cluster_t * cluster, yaml_document_t * document, yaml_node_t * node) -{ - static char fname[] = "parse_kubeconfig_yaml_clusterinfo_mapping()"; - - yaml_node_pair_t *pair = NULL; - yaml_node_t *key = NULL; - yaml_node_t *value = NULL; - - for (pair = node->data.mapping.pairs.start; pair < node->data.mapping.pairs.top; pair++) { - key = yaml_document_get_node(document, pair->key); - value = yaml_document_get_node(document, pair->value); - - if (key->type != YAML_SCALAR_NODE) { - fprintf(stderr, "%s: The key node is not YAML_SCALAR_NODE.\n", fname); - return -1; - } - - if (value->type == YAML_SCALAR_NODE) { - if (0 == strcmp(key->data.scalar.value, KEY_CERTIFICATE_AUTHORITY_DATA)) { - cluster->certificate_authority_data = strdup(value->data.scalar.value); - } else if (0 == strcmp(key->data.scalar.value, KEY_SERVER)) { - cluster->server = strdup(value->data.scalar.value); - } - } - } - - return 0; -} - -static int parse_kubeconfig_yaml_cluster_mapping(kubeconfig_cluster_t * cluster, yaml_document_t * document, yaml_node_t * node) -{ - static char fname[] = "parse_kubeconfig_yaml_cluster_mapping()"; - int rc = 0; - - yaml_node_pair_t *pair = NULL; - yaml_node_t *key = NULL; - yaml_node_t *value = NULL; - - for (pair = node->data.mapping.pairs.start; pair < node->data.mapping.pairs.top; pair++) { - key = yaml_document_get_node(document, pair->key); - value = yaml_document_get_node(document, pair->value); - - if (key->type != YAML_SCALAR_NODE) { - fprintf(stderr, "%s: The key node is not YAML_SCALAR_NODE.\n", fname); - return -1; - } - - if (value->type == YAML_SCALAR_NODE) { - if (0 == strcmp(key->data.scalar.value, KEY_NAME)) { - cluster->name = strdup(value->data.scalar.value); - } - } else if (value->type == YAML_MAPPING_NODE) { - rc = parse_kubeconfig_yaml_clusterinfo_mapping(cluster, document, value); - } - } - - return rc; -} - -static int parse_kubeconfig_yaml_clusters_sequence(kubeconfig_t * kubeconfig, yaml_document_t * document, yaml_node_t * node) -{ - int rc = 0; - yaml_node_item_t *item = NULL; - yaml_node_t *value = NULL; - int item_count = 0; - int i = 0; - - // Get the count of clusters - for (item = node->data.sequence.items.start, item_count = 0; item < node->data.sequence.items.top; item++, item_count++) { - ; - } - - kubeconfig->clusters_count = item_count; - kubeconfig->clusters = kubeconfig_clusters_create(kubeconfig->clusters_count); - - for (item = node->data.sequence.items.start, i = 0; item < node->data.sequence.items.top; item++, i++) { - value = yaml_document_get_node(document, *item); - rc = parse_kubeconfig_yaml_cluster_mapping(kubeconfig->clusters[i], document, value); - } - - return rc; } @@ -307,11 +163,11 @@ static int parse_kubeconfig_yaml_top_mapping(kubeconfig_t * kubeconfig, yaml_doc } } else { if (0 == strcmp(key->data.scalar.value, KEY_CLUSTERS)) { - rc = parse_kubeconfig_yaml_clusters_sequence(kubeconfig, document, value); + rc = parse_kubeconfig_yaml_sequence(&(kubeconfig->clusters), &(kubeconfig->clusters_count), KUBECONFIG_PROPERTY_TYPE_CLUSTER, document, value); } else if (0 == strcmp(key->data.scalar.value, KEY_CONTEXTS)) { - rc = parse_kubeconfig_yaml_contexts_sequence(kubeconfig, document, value); + rc = parse_kubeconfig_yaml_sequence(&(kubeconfig->contexts), &(kubeconfig->contexts_count), KUBECONFIG_PROPERTY_TYPE_CONTEXT, document, value); } else if (0 == strcmp(key->data.scalar.value, KEY_USERS)) { - rc = parse_kubeconfig_yaml_users_sequence(kubeconfig, document, value); + rc = parse_kubeconfig_yaml_sequence(&(kubeconfig->users), &(kubeconfig->users_count), KUBECONFIG_PROPERTY_TYPE_USER, document, value); } } }