Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support to load kubernetes configuration for memory buffer #242

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ all:
cd create_pod; make
cd list_pod_with_invalid_kubeconfig; make
cd list_pod; make
cd list_pod_buffer; make
cd list_pod_incluster; make
cd delete_pod; make
cd exec_provider; make
Expand All @@ -18,6 +19,7 @@ clean:
cd create_pod; make clean
cd list_pod_with_invalid_kubeconfig; make clean
cd list_pod; make clean
cd list_pod_buffer; make clean
cd list_pod_incluster; make clean
cd delete_pod; make clean
cd exec_provider; make clean
Expand All @@ -35,6 +37,7 @@ test:
kubectl wait --for=condition=ready --all pod -n default --timeout=60s
cd list_pod_with_invalid_kubeconfig; make test
cd list_pod; make test
cd list_pod_buffer; make test
cd delete_pod; make test
kubectl wait --for=delete pod/test-pod-6 -n default --timeout=120s
cd list_secret; make test
Expand Down
1 change: 1 addition & 0 deletions examples/list_pod_buffer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
list_pod_buffer_bin
4 changes: 4 additions & 0 deletions examples/list_pod_buffer/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
find_package(${pkgName} CONFIG REQUIRED COMPONENTS ${pkgName})

add_executable(list_pod_buffer main.c)
target_link_libraries(list_pod_buffer PRIVATE ${pkgName}::${pkgName})
17 changes: 17 additions & 0 deletions examples/list_pod_buffer/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
INCLUDE:=-I../../kubernetes/ -I/usr/local/include/kubernetes/
LIBS:=-L../../kubernetes/build -lyaml -lwebsockets -lkubernetes -L/usr/local/lib
CFLAGS:=-g
BIN:=list_pod_buffer_bin

.PHONY : all clean test memcheck
all:
gcc main.c $(CFLAGS) $(INCLUDE) $(LIBS) -o $(BIN)

test:
./$(BIN)

memcheck:
valgrind --tool=memcheck --leak-check=full ./$(BIN)

clean:
rm ./$(BIN)
148 changes: 148 additions & 0 deletions examples/list_pod_buffer/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
#include <config/kube_config.h>
#include <api/CoreV1API.h>
#include <stdio.h>

#define ENV_KUBECONFIG "KUBECONFIG"
#ifndef _WIN32
#define ENV_HOME "HOME"
#else
#define ENV_HOME "USERPROFILE"
#endif

#define KUBE_CONFIG_DEFAULT_LOCATION "%s/.kube/config"

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 {
#if defined(HAVE_SECURE_GETENV)
kubeconfig_env = secure_getenv(ENV_KUBECONFIG);
#elif defined(HAVE_GETENV)
kubeconfig_env = getenv(ENV_KUBECONFIG);
#endif
if (kubeconfig_env) {
configFileName = strdup(kubeconfig_env);
} else {
#if defined(HAVE_SECURE_GETENV)
homedir_env = secure_getenv(ENV_HOME);
#elif defined(HAVE_GETENV)
homedir_env = getenv(ENV_HOME);
#endif
if (homedir_env) {
int configFileNameSize = strlen(homedir_env) + strlen(KUBE_CONFIG_DEFAULT_LOCATION) + 1;
configFileName = calloc(configFileNameSize, sizeof(char));
if (configFileName) {
snprintf(configFileName, configFileNameSize, KUBE_CONFIG_DEFAULT_LOCATION, homedir_env);
}
}
}
}

return configFileName;
}

static char *getFileData(const char *filePath)
{
char *data = NULL;
char *kubeConfigFile = getWorkingConfigFile(filePath);
if (kubeConfigFile) {
FILE *kubeFile = fopen(kubeConfigFile, "r");
if (kubeFile) {
fseek(kubeFile, 0, SEEK_END);
long fsize = ftell(kubeFile);
fseek(kubeFile, 0, SEEK_SET);

data = calloc(1, fsize + 1);
if (data) {
fread(data, 1, fsize, kubeFile);
}

fclose(kubeFile);
} else {
printf("Could not open %s!\n", kubeConfigFile);
}

free(kubeConfigFile);
} else {
printf("Could not determine the path to kubernetes configuration file! Tried: ENV_KUBECONFIG = %s and ENV_HOME = %s\n",
getenv(ENV_KUBECONFIG), getenv(ENV_HOME) );
}


return data;
}

void list_pod(apiClient_t * apiClient)
{
v1_pod_list_t *pod_list = NULL;
pod_list = CoreV1API_listNamespacedPod(apiClient, "default", /*namespace */
NULL, /* pretty */
NULL, /* allowWatchBookmarks */
NULL, /* continue */
NULL, /* fieldSelector */
NULL, /* labelSelector */
NULL, /* limit */
NULL, /* resourceVersion */
NULL, /* resourceVersionMatch */
NULL, /* sendInitialEvents */
NULL, /* timeoutSeconds */
NULL /* watch */
);
printf("The return code of HTTP request=%ld\n", apiClient->response_code);
if (pod_list) {
printf("Get pod list:\n");
listEntry_t *listEntry = NULL;
v1_pod_t *pod = NULL;
list_ForEach(listEntry, pod_list->items) {
pod = listEntry->data;
printf("\tThe pod name: %s\n", pod->metadata->name);
}
v1_pod_list_free(pod_list);
pod_list = NULL;
} else {
printf("Cannot get any pod.\n");
}
}

int main()
{
char *basePath = NULL;
sslConfig_t *sslConfig = NULL;
list_t *apiKeys = NULL;

char *dataBuffer = getFileData(NULL); /* NULL means loading configuration from $HOME/.kube/config */
if (dataBuffer == NULL) {
printf("Cannot get kubernetes configuration from file.\n");
return -1;
}

int rc = load_kube_config_buffer(&basePath, &sslConfig, &apiKeys, dataBuffer);
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;
}

list_pod(apiClient);

apiClient_free(apiClient);
apiClient = NULL;
free_client_config(basePath, sslConfig, apiKeys);
basePath = NULL;
sslConfig = NULL;
apiKeys = NULL;
apiClient_unsetupGlobalEnv();
free(dataBuffer);
dataBuffer = NULL;

return 0;
}
49 changes: 37 additions & 12 deletions kubernetes/config/kube_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,24 +304,17 @@ static int kuberconfig_auth_provider(kubeconfig_property_t * current_user, kubec
return rc;
}

int load_kube_config(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApiKeys, const char *configFileName)
int load_kube_config_common(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApiKeys, kubeconfig_t * kubeconfig)
{
static char fname[] = "load_kube_config()";
static char fname[] = "load_kube_config_common()";
int rc = 0;
const kubeconfig_property_t *current_context = NULL;
const kubeconfig_property_t *current_cluster = NULL;
kubeconfig_property_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);
fprintf(stderr, "%s: Cannot load the kubeconfig %s\n", fname, kubeconfig->fileName ? kubeconfig->fileName : kubeconfig->buffer);
rc = -1;
goto end;
}
Expand Down Expand Up @@ -393,8 +386,40 @@ int load_kube_config(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApi
}

end:
kubeconfig_free(kubeconfig);
kubeconfig = NULL;
return rc;
}

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_t kubeconfig;
memset(&kubeconfig, 0, sizeof(kubeconfig_t));

kubeconfig.fileName = getWorkingConfigFile(configFileName);

rc = load_kube_config_common(pBasePath, pSslConfig, pApiKeys, &kubeconfig);

kubeconfig_free_members(&kubeconfig);

return rc;
}

int load_kube_config_buffer(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApiKeys, const char *buffer)
{
static char fname[] = "load_kube_config_buffer()";
int rc = 0;

kubeconfig_t kubeconfig;
memset(&kubeconfig, 0, sizeof(kubeconfig_t));

kubeconfig.buffer = strdup(buffer);

rc = load_kube_config_common(pBasePath, pSslConfig, pApiKeys, &kubeconfig);

kubeconfig_free_members(&kubeconfig);

return rc;
}

Expand Down
38 changes: 38 additions & 0 deletions kubernetes/config/kube_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,44 @@ extern "C" {

int load_kube_config(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApiKeys, const char *configFileName);

/*
* load_kube_config_buffer
*
*
* Description:
*
*
* Load kubernetes cluster configuration from specfied buffer
*
*
* Return:
*
* 0 Success
* -1 Failed
*
*
* Parameter:
*
*
* IN:

* buffer : kubernetes cluster configuration data
*
*
* 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_buffer(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApiKeys, const char *buffer);

/*
* free_client_config
*
Expand Down
15 changes: 14 additions & 1 deletion kubernetes/config/kube_config_model.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ kubeconfig_t *kubeconfig_create()
return config;
}

void kubeconfig_free(kubeconfig_t * kubeconfig)
void kubeconfig_free_members(kubeconfig_t * kubeconfig)
{
if (!kubeconfig) {
return;
Expand All @@ -224,6 +224,10 @@ void kubeconfig_free(kubeconfig_t * kubeconfig)
free(kubeconfig->fileName);
kubeconfig->fileName = NULL;
}
if (kubeconfig->buffer) {
free(kubeconfig->buffer);
kubeconfig->buffer = NULL;
}
if (kubeconfig->apiVersion) {
free(kubeconfig->apiVersion);
kubeconfig->apiVersion = NULL;
Expand Down Expand Up @@ -252,6 +256,15 @@ void kubeconfig_free(kubeconfig_t * kubeconfig)
kubeconfig_properties_free(kubeconfig->contexts, kubeconfig->contexts_count);
kubeconfig->contexts = NULL;
}
}

void kubeconfig_free(kubeconfig_t * kubeconfig)
{
if (!kubeconfig) {
return;
}

kubeconfig_free_members(kubeconfig);

free(kubeconfig);
}
Expand Down
9 changes: 9 additions & 0 deletions kubernetes/config/kube_config_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ extern "C" {

typedef struct kubeconfig_t {
char *fileName;
char *buffer;
char *apiVersion;
char *preferences;
char *kind;
Expand All @@ -112,9 +113,17 @@ extern "C" {
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);

// allocate kubeconfig_t structure on heap
kubeconfig_t *kubeconfig_create();

// free a kubeconfig_t structure allocated on heap by a call to kubeconfig_create
void kubeconfig_free(kubeconfig_t * kubeconfig);

// free internal members of a kubeconfig_t structure.
// used when releasing resources for a kubeconfig_t that was not allocated using kubeconfig_create
// for example a kubeconfig_t allocated on stack
void kubeconfig_free_members(kubeconfig_t * kubeconfig);

#ifdef __cplusplus
}
#endif
Expand Down
Loading
Loading