1143 lines
42 KiB
C
1143 lines
42 KiB
C
#include <yaml.h>
|
|
#include <errno.h>
|
|
#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_PREFERENCES "preferences"
|
|
#define KEY_CLUSTERS "clusters"
|
|
#define KEY_CLUSTER "cluster"
|
|
#define KEY_CONTEXTS "contexts"
|
|
#define KEY_CONTEXT "context"
|
|
#define KEY_NAMESPACE "namespace"
|
|
#define KEY_USERS "users"
|
|
#define KEY_USER "user"
|
|
#define KEY_NAME "name"
|
|
#define KEY_USER_EXEC "exec"
|
|
#define KEY_USER_EXEC_COMMAND "command"
|
|
#define KEY_USER_EXEC_ENV "env"
|
|
#define KEY_USER_EXEC_ENV_KEY "name"
|
|
#define KEY_USER_EXEC_ENV_VALUE "value"
|
|
#define KEY_USER_EXEC_ARGS "args"
|
|
#define KEY_USER_AUTH_PROVIDER "auth-provider"
|
|
#define KEY_USER_AUTH_PROVIDER_CONFIG "config"
|
|
#define KEY_USER_AUTH_PROVIDER_CONFIG_ACCESS_TOKEN "access-token"
|
|
#define KEY_USER_AUTH_PROVIDER_CONFIG_CLIENT_ID "client-id"
|
|
#define KEY_USER_AUTH_PROVIDER_CONFIG_CLIENT_SECRET "client-secret"
|
|
#define KEY_USER_AUTH_PROVIDER_CONFIG_CMD_PATH "cmd-path"
|
|
#define KEY_USER_AUTH_PROVIDER_CONFIG_EXPIRES_ON "expires-on"
|
|
#define KEY_USER_AUTH_PROVIDER_CONFIG_EXPIRY "expiry"
|
|
#define KEY_USER_AUTH_PROVIDER_CONFIG_ID_TOKEN "id-token"
|
|
#define KEY_USER_AUTH_PROVIDER_CONFIG_IDP_CERTIFICATE_AUTHORITY "idp-certificate-authority"
|
|
#define KEY_USER_AUTH_PROVIDER_CONFIG_IDP_CERTIFICATE_AUTHORITY_DATA "idp-certificate-authority-data"
|
|
#define KEY_USER_AUTH_PROVIDER_CONFIG_IDP_ISSUE_URL "idp-issuer-url"
|
|
#define KEY_USER_AUTH_PROVIDER_CONFIG_REFRESH_TOKEN "refresh-token"
|
|
#define KEY_CERTIFICATE_AUTHORITY_DATA "certificate-authority-data"
|
|
#define KEY_CERTIFICATE_AUTHORITY "certificate-authority"
|
|
#define KEY_INSECURE_SKIP_TLS_VERIFY "insecure-skip-tls-verify"
|
|
#define KEY_SERVER "server"
|
|
#define KEY_CLIENT_CERTIFICATE "client-certificate"
|
|
#define KEY_CLIENT_KEY "client-key"
|
|
#define KEY_CLIENT_CERTIFICATE_DATA "client-certificate-data"
|
|
#define KEY_CLIENT_KEY_DATA "client-key-data"
|
|
#define KEY_STAUTS "status"
|
|
#define KEY_TOKEN "token"
|
|
#define KEY_CLIENT_CERTIFICATE_DATA2 "clientCertificateData"
|
|
#define KEY_CLIENT_KEY_DATA2 "clientKeyData"
|
|
|
|
#define VALUE_TRUE_LOWERCASE_STRING "true"
|
|
|
|
static char *load_file_content(const char *path)
|
|
{
|
|
|
|
static char fname[] = "load_file_content()";
|
|
|
|
char *buffer;
|
|
FILE *fh = fopen(path, "rb");
|
|
|
|
if (fh == NULL) {
|
|
fprintf(stderr, "%s: Cannot parse file path: %s\n", fname, path);
|
|
return NULL;
|
|
}
|
|
|
|
fseek(fh, 0L, SEEK_END);
|
|
long s = ftell(fh);
|
|
rewind(fh);
|
|
buffer = malloc(s);
|
|
if (buffer != NULL) {
|
|
fread(buffer, s, 1, fh);
|
|
}
|
|
fclose(fh);
|
|
fh = NULL;
|
|
return buffer;
|
|
}
|
|
|
|
static int parse_kubeconfig_yaml_string_sequence(char ***p_strings, int *p_strings_count, yaml_document_t * document, yaml_node_t * node)
|
|
{
|
|
static char fname[] = "parse_kubeconfig_yaml_string_sequence()";
|
|
|
|
yaml_node_item_t *item = NULL;
|
|
yaml_node_t *value = NULL;
|
|
int item_count = 0;
|
|
int i = 0;
|
|
int rc = 0;
|
|
|
|
for (item = node->data.sequence.items.start, item_count = 0; item < node->data.sequence.items.top; item++, item_count++) {
|
|
;
|
|
}
|
|
|
|
int strings_count = item_count;
|
|
char **strings = (char **) calloc(strings_count, sizeof(char *));
|
|
if (!strings) {
|
|
fprintf(stderr, "%s: Cannot allocate memory for string sequence.\n", fname);
|
|
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);
|
|
strings[i] = strdup(value->data.scalar.value);
|
|
}
|
|
|
|
*p_strings = strings;
|
|
*p_strings_count = strings_count;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int parse_kubeconfig_yaml_string_mapping(keyValuePair_t * string_mapping, yaml_document_t * document, yaml_node_t * node)
|
|
{
|
|
static char fname[] = "parse_kubeconfig_yaml_string_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_USER_EXEC_ENV_KEY)) {
|
|
string_mapping->key = strdup(value->data.scalar.value);
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_USER_EXEC_ENV_VALUE)) {
|
|
string_mapping->value = strdup(value->data.scalar.value);
|
|
} else {
|
|
fprintf(stderr, "%s: The key of node is invalid: %s\n", fname, key->data.scalar.value);
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int parse_kubeconfig_yaml_string_mapping_sequence(keyValuePair_t *** p_string_mappings, int *p_mappings_count, yaml_document_t * document, yaml_node_t * node)
|
|
{
|
|
static char fname[] = "parse_kubeconfig_yaml_string_mapping_sequence()";
|
|
|
|
yaml_node_item_t *item = NULL;
|
|
yaml_node_t *value = NULL;
|
|
int item_count = 0;
|
|
int i = 0;
|
|
int rc = 0;
|
|
|
|
for (item = node->data.sequence.items.start, item_count = 0; item < node->data.sequence.items.top; item++, item_count++) {
|
|
;
|
|
}
|
|
|
|
int mappings_count = item_count;
|
|
keyValuePair_t **string_mappings = (keyValuePair_t **) calloc(mappings_count, sizeof(keyValuePair_t *));
|
|
if (!string_mappings) {
|
|
fprintf(stderr, "%s: Cannot allocate memory for string mappings.\n", fname);
|
|
return -1;
|
|
}
|
|
for (int j = 0; j < mappings_count; j++) {
|
|
string_mappings[j] = calloc(1, sizeof(keyValuePair_t));
|
|
if (!string_mappings[j]) {
|
|
fprintf(stderr, "%s: Cannot allocate memory for string mapping.\n", fname);
|
|
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_string_mapping(string_mappings[i], document, value);
|
|
if (0 != rc) {
|
|
fprintf(stderr, "%s: Cannot parse kubeconfig string mapping.\n", fname);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
*p_string_mappings = string_mappings;
|
|
*p_mappings_count = mappings_count;
|
|
|
|
return 0;
|
|
}
|
|
|
|
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_property_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_NAME)) {
|
|
property->name = 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_CERTIFICATE_AUTHORITY)) {
|
|
property->certificate_authority_data = load_file_content(value->data.scalar.value);
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_SERVER)) {
|
|
property->server = strdup(value->data.scalar.value);
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_INSECURE_SKIP_TLS_VERIFY)) {
|
|
property->insecure_skip_tls_verify = (0 == strcmp(value->data.scalar.value, VALUE_TRUE_LOWERCASE_STRING)); //libyaml fails to parse true, but it can parse "true"!
|
|
}
|
|
} else if (KUBECONFIG_PROPERTY_TYPE_USER == property->type) {
|
|
if (0 == strcmp(key->data.scalar.value, KEY_CLIENT_CERTIFICATE)) {
|
|
property->client_certificate_data = load_file_content(value->data.scalar.value);
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_CLIENT_KEY)) {
|
|
property->client_key_data = load_file_content(value->data.scalar.value);
|
|
} else 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 (0 == strcmp(key->data.scalar.value, KEY_TOKEN)) {
|
|
property->token = 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_NAMESPACE)) {
|
|
property->_namespace = strdup(value->data.scalar.value);
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_USER)) {
|
|
property->user = strdup(value->data.scalar.value);
|
|
}
|
|
} else if (KUBECONFIG_PROPERTY_TYPE_USER_EXEC == property->type) {
|
|
if (0 == strcmp(key->data.scalar.value, KEY_APIVERSION)) {
|
|
property->apiVersion = strdup(value->data.scalar.value);
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_USER_EXEC_COMMAND)) {
|
|
property->command = strdup(value->data.scalar.value);
|
|
}
|
|
} else if (KUBECONFIG_PROPERTY_TYPE_USER_AUTH_PROVIDER == property->type) {
|
|
if (0 == strcmp(key->data.scalar.value, KEY_USER_AUTH_PROVIDER_CONFIG_ACCESS_TOKEN)) {
|
|
property->access_token = strdup(value->data.scalar.value);
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_USER_AUTH_PROVIDER_CONFIG_CLIENT_ID)) {
|
|
property->client_id = strdup(value->data.scalar.value);
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_USER_AUTH_PROVIDER_CONFIG_CLIENT_SECRET)) {
|
|
property->client_secret = strdup(value->data.scalar.value);
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_USER_AUTH_PROVIDER_CONFIG_CMD_PATH)) {
|
|
property->cmd_path = strdup(value->data.scalar.value);
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_USER_AUTH_PROVIDER_CONFIG_EXPIRES_ON)) {
|
|
property->expires_on = strdup(value->data.scalar.value);
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_USER_AUTH_PROVIDER_CONFIG_EXPIRY)) {
|
|
property->expiry = strdup(value->data.scalar.value);
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_USER_AUTH_PROVIDER_CONFIG_ID_TOKEN)) {
|
|
property->id_token = strdup(value->data.scalar.value);
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_USER_AUTH_PROVIDER_CONFIG_IDP_CERTIFICATE_AUTHORITY)) {
|
|
property->idp_certificate_authority = strdup(value->data.scalar.value);
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_USER_AUTH_PROVIDER_CONFIG_IDP_CERTIFICATE_AUTHORITY_DATA)) {
|
|
property->idp_certificate_authority_data = strdup(value->data.scalar.value);
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_USER_AUTH_PROVIDER_CONFIG_IDP_ISSUE_URL)) {
|
|
property->idp_issuer_url = strdup(value->data.scalar.value);
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_USER_AUTH_PROVIDER_CONFIG_REFRESH_TOKEN)) {
|
|
property->refresh_token = strdup(value->data.scalar.value);
|
|
}
|
|
}
|
|
} else if (value->type == YAML_MAPPING_NODE) {
|
|
if (KUBECONFIG_PROPERTY_TYPE_USER == property->type) {
|
|
int rc = 0;
|
|
if (0 == strcmp(key->data.scalar.value, KEY_USER_EXEC)) {
|
|
property->exec = kubeconfig_property_create(KUBECONFIG_PROPERTY_TYPE_USER_EXEC);
|
|
if (!property->exec) {
|
|
fprintf(stderr, "Cannot allocate memory for kubeconfig exec for user %s.\n", property->name);
|
|
return -1;
|
|
}
|
|
rc = parse_kubeconfig_yaml_property_mapping(property->exec, document, value);
|
|
if (0 != rc) {
|
|
fprintf(stderr, "Cannot parse kubeconfig exec for user %s.\n", property->name);
|
|
return -1;
|
|
}
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_USER_AUTH_PROVIDER)) {
|
|
property->auth_provider = kubeconfig_property_create(KUBECONFIG_PROPERTY_TYPE_USER_AUTH_PROVIDER);
|
|
if (!property->auth_provider) {
|
|
fprintf(stderr, "Cannot allocate memory for kubeconfig auth provider for user %s.\n", property->name);
|
|
return -1;
|
|
}
|
|
rc = parse_kubeconfig_yaml_property_mapping(property->auth_provider, document, value);
|
|
if (0 != rc) {
|
|
fprintf(stderr, "Cannot parse kubeconfig auth provider for user %s.\n", property->name);
|
|
return -1;
|
|
}
|
|
} else {
|
|
parse_kubeconfig_yaml_property_mapping(property, document, value);
|
|
}
|
|
} else {
|
|
parse_kubeconfig_yaml_property_mapping(property, document, value);
|
|
}
|
|
} else if (value->type == YAML_SEQUENCE_NODE) {
|
|
if (KUBECONFIG_PROPERTY_TYPE_USER_EXEC == property->type) {
|
|
if (0 == strcmp(key->data.scalar.value, KEY_USER_EXEC_ENV)) {
|
|
parse_kubeconfig_yaml_string_mapping_sequence(&(property->envs), &(property->envs_count), document, value);
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_USER_EXEC_ARGS)) {
|
|
parse_kubeconfig_yaml_string_sequence(&(property->args), &(property->args_count), document, value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int parse_kubeconfig_yaml_property_sequence(kubeconfig_property_t *** p_properties, int *p_properties_count, kubeconfig_property_type_t type, yaml_document_t * document, yaml_node_t * node)
|
|
{
|
|
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 data (e.g. cluster, context, user, user_exec )
|
|
for (item = node->data.sequence.items.start, item_count = 0; item < node->data.sequence.items.top; item++, item_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_property_mapping(properties[i], document, value);
|
|
if (0 != rc) {
|
|
fprintf(stderr, "Cannot parse kubeconfig properties.\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
*p_properties = properties;
|
|
*p_properties_count = properties_count;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
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_property_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_property_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_property_sequence(&(kubeconfig->users), &(kubeconfig->users_count), KUBECONFIG_PROPERTY_TYPE_USER, 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()";
|
|
|
|
if (kubeconfig->fileName && kubeconfig->buffer) {
|
|
fprintf(stderr, "%s: Cannot use both kubeconfig->fileName and kubeconfig->buffer.\n", fname);
|
|
return -1;
|
|
}
|
|
|
|
/* Set a file input or use the provided buffer. */
|
|
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 if (kubeconfig->buffer) {
|
|
// Nothing to do here for now.
|
|
} else {
|
|
fprintf(stderr, "%s: One of the kubeconfig->fileName or kubeconfig->buffer needs to be set.\n", fname);
|
|
return -1;
|
|
}
|
|
|
|
/* Create the Parser object. */
|
|
yaml_parser_t parser;
|
|
yaml_document_t document;
|
|
|
|
yaml_parser_initialize(&parser);
|
|
if (input) {
|
|
yaml_parser_set_input_file(&parser, input);
|
|
} else {
|
|
yaml_parser_set_input_string(&parser, (const unsigned char *) kubeconfig->buffer, strlen(kubeconfig->buffer));
|
|
}
|
|
|
|
int done = 0;
|
|
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);
|
|
if (input) {
|
|
fclose(input);
|
|
}
|
|
return 0;
|
|
|
|
error:
|
|
yaml_parser_delete(&parser);
|
|
if (input) {
|
|
fclose(input);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static int parse_exec_credential_yaml_status_mapping(ExecCredential_status_t ** p_status, yaml_document_t * document, yaml_node_t * node)
|
|
{
|
|
static char fname[] = "parse_exec_credential_yaml_status_mapping()";
|
|
int rc = 0;
|
|
|
|
yaml_node_pair_t *pair = NULL;
|
|
yaml_node_t *key = NULL;
|
|
yaml_node_t *value = NULL;
|
|
|
|
ExecCredential_status_t *status = exec_credential_status_create();
|
|
if (!status) {
|
|
fprintf(stderr, "Cannot allocate memory for kubeconfig exec credentail status.\n");
|
|
return -1;
|
|
}
|
|
|
|
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_TOKEN)) {
|
|
status->token = strdup(value->data.scalar.value);
|
|
status->type = EXEC_CREDENTIAL_TYPE_TOKEN;
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_CLIENT_CERTIFICATE_DATA2)) {
|
|
status->clientCertificateData = strdup(value->data.scalar.value);
|
|
status->type = EXEC_CREDENTIAL_TYPE_CLIENT_CERT;
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_CLIENT_KEY_DATA2)) {
|
|
status->clientKeyData = strdup(value->data.scalar.value);
|
|
status->type = EXEC_CREDENTIAL_TYPE_CLIENT_CERT;
|
|
}
|
|
}
|
|
}
|
|
|
|
*p_status = status;
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int parse_exec_credential_yaml_top_mapping(ExecCredential_t * exec_credential, yaml_document_t * document, yaml_node_t * node)
|
|
{
|
|
static char fname[] = "parse_exec_credential_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)) {
|
|
exec_credential->apiVersion = strdup(value->data.scalar.value);
|
|
} else if (0 == strcmp(key->data.scalar.value, KEY_KIND)) {
|
|
exec_credential->kind = strdup(value->data.scalar.value);
|
|
}
|
|
} else {
|
|
if (0 == strcmp(key->data.scalar.value, KEY_STAUTS)) {
|
|
rc = parse_exec_credential_yaml_status_mapping(&(exec_credential->status), document, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int parse_exec_credential_yaml_node(ExecCredential_t * exec_credential, yaml_document_t * document, yaml_node_t * node)
|
|
{
|
|
static char fname[] = "parse_exec_credential_yaml_node()";
|
|
int rc = 0;
|
|
|
|
if (YAML_MAPPING_NODE == node->type) {
|
|
rc = parse_exec_credential_yaml_top_mapping(exec_credential, document, node);
|
|
} else {
|
|
fprintf(stderr, "%s: This is not a valid exec credential string.\n", fname);
|
|
rc = -1;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int parse_exec_credential_yaml_document(ExecCredential_t * exec_credential, yaml_document_t * document)
|
|
{
|
|
static char fname[] = "parse_exec_credential_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_exec_credential_yaml_node(exec_credential, document, root);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int kubeyaml_parse_exec_crendential(ExecCredential_t * exec_credential, const char *exec_credential_string)
|
|
{
|
|
static char fname[] = "kubeyaml_parse_ExecCrendentail()";
|
|
|
|
yaml_parser_t parser;
|
|
yaml_document_t document;
|
|
|
|
int done = 0;
|
|
|
|
/* Create the Parser object. */
|
|
yaml_parser_initialize(&parser);
|
|
|
|
/* Set a string input. */
|
|
yaml_parser_set_input_string(&parser, exec_credential_string, strlen(exec_credential_string));
|
|
|
|
while (!done) {
|
|
|
|
if (!yaml_parser_load(&parser, &document)) {
|
|
goto error;
|
|
}
|
|
|
|
done = (!yaml_document_get_root_node(&document));
|
|
|
|
if (!done) {
|
|
parse_exec_credential_yaml_document(exec_credential, &document);
|
|
}
|
|
|
|
yaml_document_delete(&document);
|
|
|
|
}
|
|
|
|
/* Cleanup */
|
|
yaml_parser_delete(&parser);
|
|
return 0;
|
|
|
|
error:
|
|
yaml_parser_delete(&parser);
|
|
return -1;
|
|
}
|
|
|
|
static int append_key_stringvalue_to_mapping_node(yaml_document_t * output_document, int parent_node, const char *key_string, const char *value_string)
|
|
{
|
|
int key = yaml_document_add_scalar(output_document, NULL, (yaml_char_t *) key_string, -1, YAML_PLAIN_SCALAR_STYLE);
|
|
if (!key) {
|
|
return -1;
|
|
}
|
|
int value = yaml_document_add_scalar(output_document, NULL, (yaml_char_t *) value_string, -1, YAML_PLAIN_SCALAR_STYLE);
|
|
if (!value) {
|
|
return -1;
|
|
}
|
|
if (!yaml_document_append_mapping_pair(output_document, parent_node, key, value)) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int append_key_stringseq_to_mapping_node(yaml_document_t * output_document, int parent_node, const char *key_string, char **strings, int strings_count)
|
|
{
|
|
int key = yaml_document_add_scalar(output_document, NULL, (yaml_char_t *) key_string, -1, YAML_PLAIN_SCALAR_STYLE);
|
|
if (!key) {
|
|
return -1;
|
|
}
|
|
int seq = yaml_document_add_sequence(output_document, NULL, YAML_BLOCK_SEQUENCE_STYLE);
|
|
if (!seq) {
|
|
return -1;
|
|
}
|
|
if (!yaml_document_append_mapping_pair(output_document, parent_node, key, seq)) {
|
|
return -1;
|
|
}
|
|
|
|
for (int i = 0; i < strings_count; i++) {
|
|
int value = yaml_document_add_scalar(output_document, NULL, (yaml_char_t *) strings[i], -1, YAML_PLAIN_SCALAR_STYLE);
|
|
if (!value) {
|
|
return -1;
|
|
}
|
|
if (!yaml_document_append_sequence_item(output_document, seq, value)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int append_auth_provider_config_to_mapping_node(yaml_document_t * output_document, int parent_node, const kubeconfig_property_t * auth_provider_config)
|
|
{
|
|
/* Add 'name': '' */
|
|
if (auth_provider_config->name) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, parent_node, KEY_NAME, auth_provider_config->name)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'config': {} */
|
|
int key = yaml_document_add_scalar(output_document, NULL, (yaml_char_t *) KEY_USER_AUTH_PROVIDER_CONFIG, -1, YAML_PLAIN_SCALAR_STYLE);
|
|
if (!key) {
|
|
return -1;
|
|
}
|
|
int map = yaml_document_add_mapping(output_document, NULL, YAML_BLOCK_MAPPING_STYLE);
|
|
if (!map) {
|
|
return -1;
|
|
}
|
|
if (!yaml_document_append_mapping_pair(output_document, parent_node, key, map)) {
|
|
return -1;
|
|
}
|
|
|
|
/* Add 'access-token': '' */
|
|
if (auth_provider_config->access_token) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_USER_AUTH_PROVIDER_CONFIG_ACCESS_TOKEN, auth_provider_config->access_token)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'client-id': '' */
|
|
if (auth_provider_config->client_id) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_USER_AUTH_PROVIDER_CONFIG_CLIENT_ID, auth_provider_config->client_id)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'client-secret': '' */
|
|
if (auth_provider_config->client_secret) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_USER_AUTH_PROVIDER_CONFIG_CLIENT_SECRET, auth_provider_config->client_secret)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'cmd-path': '' */
|
|
if (auth_provider_config->cmd_path) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_USER_AUTH_PROVIDER_CONFIG_CMD_PATH, auth_provider_config->cmd_path)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'expires-on': '' */
|
|
if (auth_provider_config->expires_on) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_USER_AUTH_PROVIDER_CONFIG_EXPIRES_ON, auth_provider_config->expires_on)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'expiry': '' */
|
|
if (auth_provider_config->expiry) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_USER_AUTH_PROVIDER_CONFIG_EXPIRY, auth_provider_config->expiry)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'id-token': '' */
|
|
if (auth_provider_config->id_token) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_USER_AUTH_PROVIDER_CONFIG_ID_TOKEN, auth_provider_config->id_token)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'idp-certificate-authority': '' */
|
|
if (auth_provider_config->idp_certificate_authority) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_USER_AUTH_PROVIDER_CONFIG_IDP_CERTIFICATE_AUTHORITY, auth_provider_config->idp_certificate_authority)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'idp-certificate-authority-data': '' */
|
|
if (auth_provider_config->idp_certificate_authority_data) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_USER_AUTH_PROVIDER_CONFIG_IDP_CERTIFICATE_AUTHORITY_DATA, auth_provider_config->idp_certificate_authority_data)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'idp-issuer-url': '' */
|
|
if (auth_provider_config->idp_issuer_url) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_USER_AUTH_PROVIDER_CONFIG_IDP_ISSUE_URL, auth_provider_config->idp_issuer_url)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'refresh-token': '' */
|
|
if (auth_provider_config->refresh_token) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_USER_AUTH_PROVIDER_CONFIG_REFRESH_TOKEN, auth_provider_config->refresh_token)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int append_key_kvpseq_to_mapping_node(yaml_document_t * output_document, int parent_node, const char *key_string, keyValuePair_t ** kvps, int kvps_count)
|
|
{
|
|
int key = yaml_document_add_scalar(output_document, NULL, (yaml_char_t *) key_string, -1, YAML_PLAIN_SCALAR_STYLE);
|
|
if (!key) {
|
|
return -1;
|
|
}
|
|
int seq = yaml_document_add_sequence(output_document, NULL, YAML_BLOCK_SEQUENCE_STYLE);
|
|
if (!seq) {
|
|
return -1;
|
|
}
|
|
if (!yaml_document_append_mapping_pair(output_document, parent_node, key, seq)) {
|
|
return -1;
|
|
}
|
|
|
|
for (int i = 0; i < kvps_count; i++) {
|
|
int map = yaml_document_add_mapping(output_document, NULL, YAML_BLOCK_MAPPING_STYLE);
|
|
if (!map) {
|
|
return -1;
|
|
}
|
|
if (!yaml_document_append_sequence_item(output_document, seq, map)) {
|
|
return -1;
|
|
}
|
|
|
|
/* Add 'name': '' */
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_USER_EXEC_ENV_KEY, kvps[i]->key)) {
|
|
return -1;
|
|
}
|
|
|
|
/* Add 'value': '' */
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_USER_EXEC_ENV_VALUE, kvps[i]->value)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int append_key_map_to_mapping_node(yaml_document_t * output_document, int parent_node, const char *key_string, const kubeconfig_property_t * property)
|
|
{
|
|
int key = yaml_document_add_scalar(output_document, NULL, (yaml_char_t *) key_string, -1, YAML_PLAIN_SCALAR_STYLE);
|
|
if (!key) {
|
|
return -1;
|
|
}
|
|
int map = yaml_document_add_mapping(output_document, NULL, YAML_BLOCK_MAPPING_STYLE);
|
|
if (!map) {
|
|
return -1;
|
|
}
|
|
if (!yaml_document_append_mapping_pair(output_document, parent_node, key, map)) {
|
|
return -1;
|
|
}
|
|
|
|
if (!property) {
|
|
return 0;
|
|
}
|
|
|
|
if (KUBECONFIG_PROPERTY_TYPE_CONTEXT == property->type) {
|
|
/* Add 'cluster': '' */
|
|
if (property->cluster) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_CLUSTER, property->cluster)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'namespace': '' */
|
|
if (property->_namespace) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_NAMESPACE, property->_namespace)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'user': '' */
|
|
if (property->user) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_USER, property->user)) {
|
|
return -1;
|
|
}
|
|
}
|
|
} else if (KUBECONFIG_PROPERTY_TYPE_CLUSTER == property->type) {
|
|
/* Add 'certificate-authority-data': '' */
|
|
if (property->certificate_authority_data) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_CERTIFICATE_AUTHORITY_DATA, property->certificate_authority_data)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'server': '' */
|
|
if (property->server) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_SERVER, property->server)) {
|
|
return -1;
|
|
}
|
|
}
|
|
} else if (KUBECONFIG_PROPERTY_TYPE_USER == property->type) {
|
|
/* Add 'auth-provider': {} */
|
|
if (property->auth_provider) {
|
|
if (-1 == append_key_map_to_mapping_node(output_document, map, KEY_USER_AUTH_PROVIDER, property->auth_provider)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'client-certificate-data': '' */
|
|
if (property->client_certificate_data) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_CLIENT_CERTIFICATE_DATA, property->client_certificate_data)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'client-key-data': '' */
|
|
if (property->client_key_data) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_CLIENT_KEY_DATA, property->client_key_data)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'exec': {} */
|
|
if (property->exec) {
|
|
if (-1 == append_key_map_to_mapping_node(output_document, map, KEY_USER_EXEC, property->exec)) {
|
|
return -1;
|
|
}
|
|
}
|
|
} else if (KUBECONFIG_PROPERTY_TYPE_USER_EXEC == property->type) {
|
|
/* Add 'apiVersion': '' */
|
|
if (property->apiVersion) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_APIVERSION, property->apiVersion)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'args': [] */
|
|
if (property->args && property->args_count > 0) {
|
|
if (-1 == append_key_stringseq_to_mapping_node(output_document, map, KEY_USER_EXEC_ARGS, property->args, property->args_count)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'command': '' */
|
|
if (property->command) {
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_USER_EXEC_COMMAND, property->command)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'env': [] */
|
|
if (property->envs && property->envs_count > 0) {
|
|
if (-1 == append_key_kvpseq_to_mapping_node(output_document, map, KEY_USER_EXEC_ENV, property->envs, property->envs_count)) {
|
|
return -1;
|
|
}
|
|
}
|
|
} else if (KUBECONFIG_PROPERTY_TYPE_USER_AUTH_PROVIDER == property->type) {
|
|
if (-1 == append_auth_provider_config_to_mapping_node(output_document, map, property)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int append_key_seq_to_top_mapping_node(yaml_document_t * output_document, int parent_node, const char *first_level_key_string, const char *second_level_key_string,
|
|
kubeconfig_property_t ** properites, int properites_count)
|
|
{
|
|
int key = yaml_document_add_scalar(output_document, NULL, (yaml_char_t *) first_level_key_string, -1, YAML_PLAIN_SCALAR_STYLE);
|
|
if (!key) {
|
|
return -1;
|
|
}
|
|
int seq = yaml_document_add_sequence(output_document, NULL, YAML_BLOCK_SEQUENCE_STYLE);
|
|
if (!seq) {
|
|
return -1;
|
|
}
|
|
if (!yaml_document_append_mapping_pair(output_document, parent_node, key, seq)) {
|
|
return -1;
|
|
}
|
|
|
|
for (int i = 0; i < properites_count; i++) {
|
|
/* Add {}. */
|
|
int map = yaml_document_add_mapping(output_document, NULL, YAML_BLOCK_MAPPING_STYLE);
|
|
if (!map) {
|
|
return -1;
|
|
}
|
|
if (!yaml_document_append_sequence_item(output_document, seq, map)) {
|
|
return -1;
|
|
}
|
|
|
|
if (NULL != strstr(second_level_key_string, KEY_CLUSTER) || NULL != strstr(second_level_key_string, KEY_CONTEXT)) {
|
|
/* Add 'cluster/context': {} */
|
|
if (-1 == append_key_map_to_mapping_node(output_document, map, second_level_key_string, properites[i])) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Add 'name': '' */
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, map, KEY_NAME, properites[i]->name)) {
|
|
return -1;
|
|
}
|
|
|
|
if (NULL != strstr(second_level_key_string, KEY_USER)) {
|
|
/* Add 'user': {} */
|
|
if (-1 == append_key_map_to_mapping_node(output_document, map, second_level_key_string, properites[i])) {
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int fill_yaml_document(yaml_document_t * output_document, const kubeconfig_t * kubeconfig)
|
|
{
|
|
int root = yaml_document_add_mapping(output_document, NULL, YAML_BLOCK_MAPPING_STYLE);
|
|
if (!root) {
|
|
return -1;
|
|
}
|
|
|
|
/* Add 'apiVersion': '' */
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, root, KEY_APIVERSION, kubeconfig->apiVersion)) {
|
|
return -1;
|
|
}
|
|
|
|
/* Add 'clusters': {} */
|
|
if (-1 == append_key_seq_to_top_mapping_node(output_document, root, KEY_CLUSTERS, KEY_CLUSTER, kubeconfig->clusters, kubeconfig->clusters_count)) {
|
|
return -1;
|
|
}
|
|
|
|
/* Add 'contexts': {} */
|
|
if (-1 == append_key_seq_to_top_mapping_node(output_document, root, KEY_CONTEXTS, KEY_CONTEXT, kubeconfig->contexts, kubeconfig->contexts_count)) {
|
|
return -1;
|
|
}
|
|
|
|
/* Add 'current-context': '' */
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, root, KEY_CURRENT_CONTEXT, kubeconfig->current_context)) {
|
|
return -1;
|
|
}
|
|
|
|
/* Add 'kind': 'Config' */
|
|
if (-1 == append_key_stringvalue_to_mapping_node(output_document, root, KEY_KIND, kubeconfig->kind)) {
|
|
return -1;
|
|
}
|
|
|
|
/* Add 'preferences': {} */
|
|
if (-1 == append_key_map_to_mapping_node(output_document, root, KEY_PREFERENCES, NULL)) {
|
|
return -1;
|
|
}
|
|
|
|
/* Add 'users': {} */
|
|
if (-1 == append_key_seq_to_top_mapping_node(output_document, root, KEY_USERS, KEY_USER, kubeconfig->users, kubeconfig->users_count)) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int kubeyaml_save_kubeconfig(const kubeconfig_t * kubeconfig)
|
|
{
|
|
static char fname[] = "kubeyaml_save_kubeconfig()";
|
|
|
|
if (!kubeconfig) {
|
|
return 0;
|
|
}
|
|
|
|
/* Set a file output. */
|
|
FILE *output = NULL;
|
|
if (kubeconfig->fileName) {
|
|
output = fopen(kubeconfig->fileName, "wb");
|
|
if (!output) {
|
|
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_emitter_t emitter;
|
|
yaml_document_t output_document;
|
|
|
|
memset(&emitter, 0, sizeof(emitter));
|
|
memset(&output_document, 0, sizeof(output_document));
|
|
|
|
/* Initialize the emitter object. */
|
|
if (!yaml_emitter_initialize(&emitter)) {
|
|
fprintf(stderr, "%s: Could not initialize the emitter object\n", fname);
|
|
fclose(output);
|
|
return -1;
|
|
}
|
|
|
|
/* Set the emitter parameters. */
|
|
yaml_emitter_set_canonical(&emitter, 0);
|
|
yaml_emitter_set_unicode(&emitter, 1);
|
|
yaml_emitter_set_output_file(&emitter, output);
|
|
|
|
/* Create and emit the STREAM-START event. */
|
|
if (!yaml_emitter_open(&emitter)) {
|
|
goto emitter_error;
|
|
}
|
|
|
|
/* Create a output_document object. */
|
|
if (!yaml_document_initialize(&output_document, NULL, NULL, NULL, 0, 0)) {
|
|
goto document_error;
|
|
}
|
|
|
|
if (-1 == fill_yaml_document(&output_document, kubeconfig)) {
|
|
goto document_error;
|
|
}
|
|
|
|
/* Emit the event. */
|
|
if (!yaml_emitter_dump(&emitter, &output_document)) {
|
|
goto emitter_error;
|
|
}
|
|
yaml_emitter_flush(&emitter);
|
|
|
|
if (!yaml_emitter_close(&emitter)) {
|
|
goto emitter_error;
|
|
}
|
|
|
|
yaml_emitter_delete(&emitter);
|
|
yaml_document_delete(&output_document);
|
|
fclose(output);
|
|
|
|
return 0;
|
|
|
|
emitter_error:
|
|
|
|
switch (emitter.error) {
|
|
case YAML_MEMORY_ERROR:
|
|
fprintf(stderr, "%s: Memory error: Not enough memory for emitting\n", fname);
|
|
break;
|
|
|
|
case YAML_WRITER_ERROR:
|
|
fprintf(stderr, "%s: Writer error: %s\n", fname, emitter.problem);
|
|
break;
|
|
|
|
case YAML_EMITTER_ERROR:
|
|
fprintf(stderr, "%s: Emitter error: %s\n", fname, emitter.problem);
|
|
break;
|
|
|
|
default:
|
|
/* Couldn't happen. */
|
|
fprintf(stderr, "%s: Internal error\n", fname);
|
|
break;
|
|
}
|
|
|
|
yaml_document_delete(&output_document);
|
|
yaml_emitter_delete(&emitter);
|
|
fclose(output);
|
|
|
|
return -1;
|
|
|
|
document_error:
|
|
|
|
fprintf(stderr, "%s: Memory error: Not enough memory for creating a document\n", fname);
|
|
yaml_document_delete(&output_document);
|
|
yaml_emitter_delete(&emitter);
|
|
fclose(output);
|
|
|
|
return -1;
|
|
}
|