Merge pull request #10 from ityuhui/yhinclusterconfig
[Configuration]Support bearer tokens in cluster
This commit is contained in:
@@ -15,14 +15,17 @@ void create_a_pod(apiClient_t * apiClient)
|
||||
podinfo->spec = calloc(1, sizeof(v1_pod_spec_t));
|
||||
|
||||
podinfo->metadata = calloc(1, sizeof(v1_object_meta_t));
|
||||
/* set pod name */
|
||||
podinfo->metadata->name = strdup("test-pod-6");
|
||||
|
||||
/* set containers for pod */
|
||||
list_t *containerlist = list_create();
|
||||
v1_container_t *con = calloc(1, sizeof(v1_container_t));
|
||||
con->name = strdup("my-container");
|
||||
con->image = strdup("ubuntu:16.04");
|
||||
con->image = strdup("ubuntu:latest");
|
||||
con->image_pull_policy = strdup("IfNotPresent");
|
||||
|
||||
/* set command for container */
|
||||
list_t *commandlist = list_create();
|
||||
char *cmd = strdup("sleep");
|
||||
list_addElement(commandlist, cmd);
|
||||
@@ -33,9 +36,28 @@ void create_a_pod(apiClient_t * apiClient)
|
||||
list_addElement(arglist, arg1);
|
||||
con->args = arglist;
|
||||
|
||||
/* set volume mounts for container */
|
||||
list_t *volumemounts = list_create();
|
||||
v1_volume_mount_t *volmou = v1_volume_mount_create("/test", NULL, "test", 0, NULL, NULL);
|
||||
list_addElement(volumemounts, volmou);
|
||||
con->volume_mounts = volumemounts;
|
||||
|
||||
list_addElement(containerlist, con);
|
||||
podinfo->spec->containers = containerlist;
|
||||
|
||||
/* set volumes for pod */
|
||||
list_t *volumelist = list_create();
|
||||
v1_volume_t *volume = calloc(1, sizeof(v1_volume_t));
|
||||
volume->name = strdup("test");
|
||||
|
||||
v1_host_path_volume_source_t *hostPath = calloc(1, sizeof(v1_host_path_volume_source_t));
|
||||
hostPath->path = strdup("/test");
|
||||
volume->host_path = hostPath;
|
||||
|
||||
list_addElement(volumelist, volume);
|
||||
podinfo->spec->volumes = volumelist;
|
||||
|
||||
/* call API in libkubernetes to create pod */
|
||||
v1_pod_t *apod = CoreV1API_createNamespacedPod(apiClient, namespace, podinfo, NULL, NULL, NULL);
|
||||
printf("code=%ld\n", apiClient->response_code);
|
||||
|
||||
|
||||
1
examples/list_pod_incluster/.gitignore
vendored
Normal file
1
examples/list_pod_incluster/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
list_pod_incluster_bin
|
||||
8
examples/list_pod_incluster/Makefile
Normal file
8
examples/list_pod_incluster/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
INCLUDE:=-I../../kubernetes/include -I../../kubernetes/model -I../../kubernetes/api -I../../kubernetes/config
|
||||
LIBS:=-L../../kubernetes/build -lkubernetes -lcurl -lyaml -lpthread -lssl -lz
|
||||
CFLAGS:=-g
|
||||
|
||||
all:
|
||||
gcc main.c $(CFLAGS) $(INCLUDE) $(LIBS) -o list_pod_incluster_bin
|
||||
clean:
|
||||
rm ./list_pod_incluster_bin
|
||||
67
examples/list_pod_incluster/main.c
Normal file
67
examples/list_pod_incluster/main.c
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <incluster_config.h>
|
||||
#include <kube_config.h>
|
||||
#include <apiClient.h>
|
||||
#include <CoreV1API.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
void list_pod(apiClient_t * apiClient)
|
||||
{
|
||||
v1_pod_list_t *pod_list = NULL;
|
||||
pod_list = CoreV1API_listNamespacedPod(apiClient, "default", /*namespace */
|
||||
NULL, /* pretty */
|
||||
0, /* allowWatchBookmarks */
|
||||
NULL, /* continue */
|
||||
NULL, /* fieldSelector */
|
||||
NULL, /* labelSelector */
|
||||
0, /* limit */
|
||||
NULL, /* resourceVersion */
|
||||
0, /* timeoutSeconds */
|
||||
0 /* 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);
|
||||
}
|
||||
} else {
|
||||
printf("Cannot get any pod.\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
char *baseName = NULL;
|
||||
sslConfig_t *sslConfig = NULL;
|
||||
list_t *apiKeys = NULL;
|
||||
apiClient_t *k8sApiClient = NULL;
|
||||
|
||||
rc = load_incluster_config(&baseName, &sslConfig, &apiKeys);
|
||||
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;
|
||||
}
|
||||
@@ -24,6 +24,7 @@ set(SRCS
|
||||
config/kube_config_model.c
|
||||
config/kube_config_yaml.c
|
||||
config/kube_config.c
|
||||
config/incluster_config.c
|
||||
src/list.c
|
||||
src/apiKey.c
|
||||
src/apiClient.c
|
||||
@@ -778,6 +779,7 @@ set(HDRS
|
||||
config/kube_config_model.h
|
||||
config/kube_config_yaml.h
|
||||
config/kube_config.h
|
||||
config/incluster_config.h
|
||||
include/apiClient.h
|
||||
include/list.h
|
||||
include/keyValuePair.h
|
||||
|
||||
167
kubernetes/config/incluster_config.c
Normal file
167
kubernetes/config/incluster_config.c
Normal file
@@ -0,0 +1,167 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include "incluster_config.h"
|
||||
|
||||
#define SERVICE_HOST_ENV_NAME "KUBERNETES_SERVICE_HOST"
|
||||
#define SERVICE_PORT_ENV_NAME "KUBERNETES_SERVICE_PORT"
|
||||
#define SERVICE_HTTPS_PREFIX "https://"
|
||||
#define SERVICE_TOKEN_FILENAME "/var/run/secrets/kubernetes.io/serviceaccount/token"
|
||||
#define SERVICE_CERT_FILENAME "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
|
||||
#define AUTH_TOKEN_KEY "Authorization"
|
||||
#define BEARER_TOKEN_TEMPLATE "Bearer %s"
|
||||
#define BEARER_TOKEN_BUFFER_SIZE 1024
|
||||
|
||||
static int checkServiceAccountFile(const char *fileName)
|
||||
{
|
||||
static char fname[] = "checkServiceAccountFile()";
|
||||
|
||||
if (!fileName) {
|
||||
fprintf(stderr, "%s: The file name must be specified.\n", fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct stat info;
|
||||
if (-1 == stat(fileName, &info)) {
|
||||
switch (errno) {
|
||||
case ENOENT:
|
||||
fprintf(stderr, "%s: The file %s does not exist.[%s]\n", fname, fileName, strerror(errno));
|
||||
return -1;
|
||||
case EACCES:
|
||||
fprintf(stderr, "%s: No permission to read the file %s.[%s]\n", fname, fileName, strerror(errno));
|
||||
return -1;
|
||||
default:
|
||||
fprintf(stderr, "%s: Cannot retrieve the information of file %s.[%s]\n", fname, fileName, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setBasePathInCluster(char **pBasePath)
|
||||
{
|
||||
static char fname[] = "setBasePathInCluster()";
|
||||
|
||||
const char *service_host_env = secure_getenv(SERVICE_HOST_ENV_NAME);
|
||||
if (!service_host_env) {
|
||||
fprintf(stderr, "%s: Cannot retrieve the kubernetes service host inside a pod by the env %s.\n", fname, SERVICE_HOST_ENV_NAME);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *service_port_env = secure_getenv(SERVICE_PORT_ENV_NAME);
|
||||
if (!service_port_env) {
|
||||
fprintf(stderr, "%s: Cannot retrieve the kubernetes service port inside a pod by the env %s.\n", fname, SERVICE_PORT_ENV_NAME);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int basePathSize = strlen(SERVICE_HTTPS_PREFIX) + strlen(service_host_env) + strlen(service_port_env) + 2 /* 1 for ':', 1 for '\0' */ ;
|
||||
char *basePath = calloc(basePathSize, sizeof(char));
|
||||
if (!basePath) {
|
||||
fprintf(stderr, "%s: Cannot allocate the memory for base path for kubernetes service.\n", fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(basePath, basePathSize, "%s%s:%s", SERVICE_HTTPS_PREFIX, service_host_env, service_port_env);
|
||||
*pBasePath = basePath;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setSslConfigInCluster(sslConfig_t ** pSslConfig, const char *caFileName)
|
||||
{
|
||||
static char fname[] = "setSslConfigInCluster()";
|
||||
|
||||
if (0 != checkServiceAccountFile(caFileName)) {
|
||||
fprintf(stderr, "%s: Cannot retrieve the CA for kubernetes service in the pod.\n", fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sslConfig_t *sc = sslConfig_create(NULL, /* client certificate */
|
||||
NULL, /* client private key */
|
||||
caFileName, /* CA file */
|
||||
0 /* 0 means the server certificate is required to be verified by CA */
|
||||
);
|
||||
if (!sc) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pSslConfig = sc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int readTokenInCluster(char *token, int token_buf_size)
|
||||
{
|
||||
static char fname[] = "readTokenInCluster()";
|
||||
|
||||
if (0 != checkServiceAccountFile(SERVICE_TOKEN_FILENAME)) {
|
||||
fprintf(stderr, "%s: Cannot retrieve the token for kubernetes service in the pod.\n", fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE *fp;
|
||||
fp = fopen(SERVICE_TOKEN_FILENAME, "r");
|
||||
if (NULL == fp) {
|
||||
fprintf(stderr, "%s: Failed to open file %s.[%s]", fname, SERVICE_TOKEN_FILENAME, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *read_str = fgets(token, token_buf_size, fp);
|
||||
fclose(fp);
|
||||
if (NULL == read_str) {
|
||||
fprintf(stderr, "%s: Cannot read token from the file %s.[%s]", fname, SERVICE_TOKEN_FILENAME, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setApiKeysInCluster(list_t ** pApiKeys)
|
||||
{
|
||||
static char fname[] = "setApiKeysInCluster()";
|
||||
|
||||
list_t *apiKeys = list_create();
|
||||
if (!apiKeys) {
|
||||
fprintf(stderr, "%s: Cannot allocate the memory for api kyes for kubernetes service.\n", fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char token[BEARER_TOKEN_BUFFER_SIZE];
|
||||
memset(token, 0, sizeof(token));
|
||||
if (0 == readTokenInCluster(token, BEARER_TOKEN_BUFFER_SIZE)) {
|
||||
char tokenValue[BEARER_TOKEN_BUFFER_SIZE];
|
||||
memset(tokenValue, 0, sizeof(tokenValue));
|
||||
snprintf(tokenValue, BEARER_TOKEN_BUFFER_SIZE, BEARER_TOKEN_TEMPLATE, token);
|
||||
keyValuePair_t *keyPairToken = keyValuePair_create(strdup(AUTH_TOKEN_KEY), strdup(tokenValue));
|
||||
list_addElement(apiKeys, keyPairToken);
|
||||
} else {
|
||||
fprintf(stderr, "%s: Cannot retrieve the service token in the pod.", fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pApiKeys = apiKeys;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_incluster_config(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApiKeys)
|
||||
{
|
||||
static char fname[] = "load_incluster_config()";
|
||||
|
||||
if (0 != setBasePathInCluster(pBasePath)) {
|
||||
fprintf(stderr, "%s: Cannot set the base path for API server inside cluster.\n", fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 != setSslConfigInCluster(pSslConfig, SERVICE_CERT_FILENAME)) {
|
||||
fprintf(stderr, "%s: Cannot set the SSL Configuration for the client inside cluster.\n", fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 != setApiKeysInCluster(pApiKeys)) {
|
||||
fprintf(stderr, "%s: Cannot set the service tokens for the client inside cluster.\n", fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
52
kubernetes/config/incluster_config.h
Normal file
52
kubernetes/config/incluster_config.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef _INCLUSTER_CONFIG_H
|
||||
#define _INCLUSTER_CONFIG_H
|
||||
|
||||
#include "../include/apiClient.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* load_incluster_config
|
||||
*
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
*
|
||||
* Load kubernetes cluster configuration from service account
|
||||
* files inside a pod
|
||||
*
|
||||
*
|
||||
* Return:
|
||||
*
|
||||
* 0 Success
|
||||
* -1 Failed
|
||||
*
|
||||
*
|
||||
* Parameter:
|
||||
*
|
||||
*
|
||||
* IN:
|
||||
|
||||
* None
|
||||
*
|
||||
*
|
||||
* 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_incluster_config(char **pBasePath, sslConfig_t ** pSslConfig, list_t ** pApiKeys);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _INCLUSTER_CONFIG_H */
|
||||
@@ -1,8 +1,10 @@
|
||||
#include "kube_config.h"
|
||||
#include "kube_config_yaml.h"
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include "kube_config.h"
|
||||
#include "kube_config_yaml.h"
|
||||
|
||||
#define ENV_KUBECONFIG "KUBECONFIG"
|
||||
#define ENV_HOME "HOME"
|
||||
@@ -137,15 +139,16 @@ static char *getWorkingConfigFile(const char *configFileNamePassedIn)
|
||||
if (configFileNamePassedIn) {
|
||||
configFileName = strdup(configFileNamePassedIn);
|
||||
} else {
|
||||
kubeconfig_env = getenv(ENV_KUBECONFIG);
|
||||
kubeconfig_env = secure_getenv(ENV_KUBECONFIG);
|
||||
if (kubeconfig_env) {
|
||||
configFileName = strdup(kubeconfig_env);
|
||||
} else {
|
||||
homedir_env = getenv(ENV_HOME);
|
||||
homedir_env = secure_getenv(ENV_HOME);
|
||||
if (homedir_env) {
|
||||
configFileName = calloc(strlen(homedir_env) + strlen(KUBE_CONFIG_DEFAULT_LOCATION) + 1, sizeof(char));
|
||||
int configFileNameSize = strlen(homedir_env) + strlen(KUBE_CONFIG_DEFAULT_LOCATION) + 1;
|
||||
configFileName = calloc(configFileNameSize, sizeof(char));
|
||||
if (configFileName) {
|
||||
sprintf(configFileName, KUBE_CONFIG_DEFAULT_LOCATION, homedir_env);
|
||||
snprintf(configFileName, configFileNameSize, KUBE_CONFIG_DEFAULT_LOCATION, homedir_env);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user