Skip to content

Commit 35d313f

Browse files
authored
Merge pull request #242 from DanyT/feature/load-kubeconfig-from-memory
add support to load kubernetes configuration for memory buffer
2 parents dc7d670 + 65bcd15 commit 35d313f

File tree

11 files changed

+284
-20
lines changed

11 files changed

+284
-20
lines changed

examples/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ all:
22
cd create_pod; make
33
cd list_pod_with_invalid_kubeconfig; make
44
cd list_pod; make
5+
cd list_pod_buffer; make
56
cd list_pod_incluster; make
67
cd delete_pod; make
78
cd exec_provider; make
@@ -18,6 +19,7 @@ clean:
1819
cd create_pod; make clean
1920
cd list_pod_with_invalid_kubeconfig; make clean
2021
cd list_pod; make clean
22+
cd list_pod_buffer; make clean
2123
cd list_pod_incluster; make clean
2224
cd delete_pod; make clean
2325
cd exec_provider; make clean
@@ -35,6 +37,7 @@ test:
3537
kubectl wait --for=condition=ready --all pod -n default --timeout=60s
3638
cd list_pod_with_invalid_kubeconfig; make test
3739
cd list_pod; make test
40+
cd list_pod_buffer; make test
3841
cd delete_pod; make test
3942
kubectl wait --for=delete pod/test-pod-6 -n default --timeout=120s
4043
cd list_secret; make test
@@ -51,6 +54,7 @@ memcheck:
5154
kubectl wait --for=condition=ready --all pod -n default --timeout=60s
5255
cd list_pod_with_invalid_kubeconfig; make memcheck
5356
cd list_pod; make memcheck
57+
cd list_pod_buffer; make memcheck
5458
cd delete_pod; make memcheck
5559
kubectl wait --for=delete pod/test-pod-6 -n default --timeout=120s
5660
cd list_secret; make memcheck

examples/list_pod_buffer/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
list_pod_buffer_bin
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
find_package(${pkgName} CONFIG REQUIRED COMPONENTS ${pkgName})
2+
3+
add_executable(list_pod_buffer main.c)
4+
target_link_libraries(list_pod_buffer PRIVATE ${pkgName}::${pkgName})

examples/list_pod_buffer/Makefile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
INCLUDE:=-I../../kubernetes/ -I/usr/local/include/kubernetes/
2+
LIBS:=-L../../kubernetes/build -lyaml -lwebsockets -lkubernetes -L/usr/local/lib
3+
CFLAGS:=-g
4+
BIN:=list_pod_buffer_bin
5+
6+
.PHONY : all clean test memcheck
7+
all:
8+
gcc main.c $(CFLAGS) $(INCLUDE) $(LIBS) -o $(BIN)
9+
10+
test:
11+
./$(BIN)
12+
13+
memcheck:
14+
valgrind --tool=memcheck --leak-check=full ./$(BIN)
15+
16+
clean:
17+
rm ./$(BIN)

examples/list_pod_buffer/main.c

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
#include <config/kube_config.h>
2+
#include <api/CoreV1API.h>
3+
#include <stdio.h>
4+
5+
#define ENV_KUBECONFIG "KUBECONFIG"
6+
#ifndef _WIN32
7+
#define ENV_HOME "HOME"
8+
#else
9+
#define ENV_HOME "USERPROFILE"
10+
#endif
11+
12+
#define KUBE_CONFIG_DEFAULT_LOCATION "%s/.kube/config"
13+
14+
static char *getWorkingConfigFile(const char *configFileNamePassedIn)
15+
{
16+
char *configFileName = NULL;
17+
const char *kubeconfig_env = NULL;
18+
const char *homedir_env = NULL;
19+
20+
if (configFileNamePassedIn) {
21+
configFileName = strdup(configFileNamePassedIn);
22+
} else {
23+
homedir_env = getenv(ENV_HOME);
24+
if (homedir_env) {
25+
int configFileNameSize = strlen(homedir_env) + strlen(KUBE_CONFIG_DEFAULT_LOCATION) + 1;
26+
configFileName = calloc(configFileNameSize, sizeof(char));
27+
if (configFileName) {
28+
snprintf(configFileName, configFileNameSize, KUBE_CONFIG_DEFAULT_LOCATION, homedir_env);
29+
}
30+
}
31+
}
32+
33+
return configFileName;
34+
}
35+
36+
static char *getFileData(const char *filePath)
37+
{
38+
char *data = NULL;
39+
char *kubeConfigFile = getWorkingConfigFile(filePath);
40+
if (kubeConfigFile) {
41+
FILE *kubeFile = fopen(kubeConfigFile, "r");
42+
if (kubeFile) {
43+
fseek(kubeFile, 0, SEEK_END);
44+
long fsize = ftell(kubeFile);
45+
fseek(kubeFile, 0, SEEK_SET);
46+
47+
data = calloc(1, fsize + 1);
48+
if (data) {
49+
fread(data, 1, fsize, kubeFile);
50+
}
51+
52+
fclose(kubeFile);
53+
} else {
54+
printf("Could not open %s!\n", kubeConfigFile);
55+
}
56+
57+
free(kubeConfigFile);
58+
} else {
59+
printf("Could not determine the path to kubernetes configuration file! Tried: ENV_KUBECONFIG = %s and ENV_HOME = %s\n",
60+
getenv(ENV_KUBECONFIG), getenv(ENV_HOME) );
61+
}
62+
63+
64+
return data;
65+
}
66+
67+
void list_pod(apiClient_t * apiClient)
68+
{
69+
v1_pod_list_t *pod_list = NULL;
70+
pod_list = CoreV1API_listNamespacedPod(apiClient, "default", /*namespace */
71+
NULL, /* pretty */
72+
NULL, /* allowWatchBookmarks */
73+
NULL, /* continue */
74+
NULL, /* fieldSelector */
75+
NULL, /* labelSelector */
76+
NULL, /* limit */
77+
NULL, /* resourceVersion */
78+
NULL, /* resourceVersionMatch */
79+
NULL, /* sendInitialEvents */
80+
NULL, /* timeoutSeconds */
81+
NULL /* watch */
82+
);
83+
printf("The return code of HTTP request=%ld\n", apiClient->response_code);
84+
if (pod_list) {
85+
printf("Get pod list:\n");
86+
listEntry_t *listEntry = NULL;
87+
v1_pod_t *pod = NULL;
88+
list_ForEach(listEntry, pod_list->items) {
89+
pod = listEntry->data;
90+
printf("\tThe pod name: %s\n", pod->metadata->name);
91+
}
92+
v1_pod_list_free(pod_list);
93+
pod_list = NULL;
94+
} else {
95+
printf("Cannot get any pod.\n");
96+
}
97+
}
98+
99+
int main()
100+
{
101+
char *basePath = NULL;
102+
sslConfig_t *sslConfig = NULL;
103+
list_t *apiKeys = NULL;
104+
105+
char *dataBuffer = getFileData(NULL); /* NULL means loading configuration from $HOME/.kube/config */
106+
if (dataBuffer == NULL) {
107+
printf("Cannot get kubernetes configuration from file.\n");
108+
return -1;
109+
}
110+
111+
int rc = load_kube_config_buffer(&basePath, &sslConfig, &apiKeys, dataBuffer);
112+
if (rc != 0) {
113+
printf("Cannot load kubernetes configuration.\n");
114+
return -1;
115+
}
116+
apiClient_t *apiClient = apiClient_create_with_base_path(basePath, sslConfig, apiKeys);
117+
if (!apiClient) {
118+
printf("Cannot create a kubernetes client.\n");
119+
return -1;
120+
}
121+
122+
list_pod(apiClient);
123+
124+
apiClient_free(apiClient);
125+
apiClient = NULL;
126+
free_client_config(basePath, sslConfig, apiKeys);
127+
basePath = NULL;
128+
sslConfig = NULL;
129+
apiKeys = NULL;
130+
apiClient_unsetupGlobalEnv();
131+
free(dataBuffer);
132+
dataBuffer = NULL;
133+
134+
return 0;
135+
}

kubernetes/config/kube_config.c

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -304,24 +304,17 @@ static int kuberconfig_auth_provider(kubeconfig_property_t * current_user, kubec
304304
return rc;
305305
}
306306

307-
int load_kube_config(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApiKeys, const char *configFileName)
307+
int load_kube_config_common(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApiKeys, kubeconfig_t * kubeconfig)
308308
{
309-
static char fname[] = "load_kube_config()";
309+
static char fname[] = "load_kube_config_common()";
310310
int rc = 0;
311311
const kubeconfig_property_t *current_context = NULL;
312312
const kubeconfig_property_t *current_cluster = NULL;
313313
kubeconfig_property_t *current_user = NULL;
314314

315-
kubeconfig_t *kubeconfig = kubeconfig_create();
316-
if (!kubeconfig) {
317-
fprintf(stderr, "%s: Cannot create kubeconfig.[%s]\n", fname, strerror(errno));
318-
return -1;
319-
}
320-
321-
kubeconfig->fileName = getWorkingConfigFile(configFileName);
322315
rc = kubeyaml_load_kubeconfig(kubeconfig);
323316
if (0 != rc) {
324-
fprintf(stderr, "%s: Cannot load the kubeconfig %s\n", fname, kubeconfig->fileName);
317+
fprintf(stderr, "%s: Cannot load the kubeconfig %s\n", fname, kubeconfig->fileName ? kubeconfig->fileName : kubeconfig->buffer);
325318
rc = -1;
326319
goto end;
327320
}
@@ -393,8 +386,40 @@ int load_kube_config(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApi
393386
}
394387

395388
end:
396-
kubeconfig_free(kubeconfig);
397-
kubeconfig = NULL;
389+
return rc;
390+
}
391+
392+
int load_kube_config(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApiKeys, const char *configFileName)
393+
{
394+
static char fname[] = "load_kube_config()";
395+
int rc = 0;
396+
397+
kubeconfig_t kubeconfig;
398+
memset(&kubeconfig, 0, sizeof(kubeconfig_t));
399+
400+
kubeconfig.fileName = getWorkingConfigFile(configFileName);
401+
402+
rc = load_kube_config_common(pBasePath, pSslConfig, pApiKeys, &kubeconfig);
403+
404+
kubeconfig_free_members(&kubeconfig);
405+
406+
return rc;
407+
}
408+
409+
int load_kube_config_buffer(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApiKeys, const char *buffer)
410+
{
411+
static char fname[] = "load_kube_config_buffer()";
412+
int rc = 0;
413+
414+
kubeconfig_t kubeconfig;
415+
memset(&kubeconfig, 0, sizeof(kubeconfig_t));
416+
417+
kubeconfig.buffer = strdup(buffer);
418+
419+
rc = load_kube_config_common(pBasePath, pSslConfig, pApiKeys, &kubeconfig);
420+
421+
kubeconfig_free_members(&kubeconfig);
422+
398423
return rc;
399424
}
400425

kubernetes/config/kube_config.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,44 @@ extern "C" {
4646

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

49+
/*
50+
* load_kube_config_buffer
51+
*
52+
*
53+
* Description:
54+
*
55+
*
56+
* Load kubernetes cluster configuration from specfied buffer
57+
*
58+
*
59+
* Return:
60+
*
61+
* 0 Success
62+
* -1 Failed
63+
*
64+
*
65+
* Parameter:
66+
*
67+
*
68+
* IN:
69+
70+
* buffer : kubernetes cluster configuration data
71+
*
72+
*
73+
* OUT:
74+
*
75+
* pBasePath: The pointer to API server address
76+
* pSslConfig: The pointer to SSL configuration for client
77+
* pApiKeys: The pointer to API tokens for client
78+
*
79+
* The memory will be allocated inside this function. User
80+
* should call free_client_config to free the memory after
81+
* these parameters are not used.
82+
*
83+
*/
84+
85+
int load_kube_config_buffer(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApiKeys, const char *buffer);
86+
4987
/*
5088
* free_client_config
5189
*

kubernetes/config/kube_config_model.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ kubeconfig_t *kubeconfig_create()
214214
return config;
215215
}
216216

217-
void kubeconfig_free(kubeconfig_t * kubeconfig)
217+
void kubeconfig_free_members(kubeconfig_t * kubeconfig)
218218
{
219219
if (!kubeconfig) {
220220
return;
@@ -224,6 +224,10 @@ void kubeconfig_free(kubeconfig_t * kubeconfig)
224224
free(kubeconfig->fileName);
225225
kubeconfig->fileName = NULL;
226226
}
227+
if (kubeconfig->buffer) {
228+
free(kubeconfig->buffer);
229+
kubeconfig->buffer = NULL;
230+
}
227231
if (kubeconfig->apiVersion) {
228232
free(kubeconfig->apiVersion);
229233
kubeconfig->apiVersion = NULL;
@@ -252,6 +256,15 @@ void kubeconfig_free(kubeconfig_t * kubeconfig)
252256
kubeconfig_properties_free(kubeconfig->contexts, kubeconfig->contexts_count);
253257
kubeconfig->contexts = NULL;
254258
}
259+
}
260+
261+
void kubeconfig_free(kubeconfig_t * kubeconfig)
262+
{
263+
if (!kubeconfig) {
264+
return;
265+
}
266+
267+
kubeconfig_free_members(kubeconfig);
255268

256269
free(kubeconfig);
257270
}

kubernetes/config/kube_config_model.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ extern "C" {
8888

8989
typedef struct kubeconfig_t {
9090
char *fileName;
91+
char *buffer;
9192
char *apiVersion;
9293
char *preferences;
9394
char *kind;
@@ -112,9 +113,17 @@ extern "C" {
112113
kubeconfig_property_t **kubeconfig_properties_create(int contexts_count, kubeconfig_property_type_t type);
113114
void kubeconfig_properties_free(kubeconfig_property_t ** properties, int properties_count);
114115

116+
// allocate kubeconfig_t structure on heap
115117
kubeconfig_t *kubeconfig_create();
118+
119+
// free a kubeconfig_t structure allocated on heap by a call to kubeconfig_create
116120
void kubeconfig_free(kubeconfig_t * kubeconfig);
117121

122+
// free internal members of a kubeconfig_t structure.
123+
// used when releasing resources for a kubeconfig_t that was not allocated using kubeconfig_create
124+
// for example a kubeconfig_t allocated on stack
125+
void kubeconfig_free_members(kubeconfig_t * kubeconfig);
126+
118127
#ifdef __cplusplus
119128
}
120129
#endif

0 commit comments

Comments
 (0)