/* This file is part of Eclat.
Copyright (C) 2012-2018 Sergey Poznyakoff.
Eclat is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
Eclat is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Eclat. If not, see . */
#include "eclat.h"
#include
/*
map "SnapshotId" {
type ec2;
action DescribeImages;
arguments ("Owner.1=self",
"Filter.1.Name=tag:Name",
"Filter.1.Value.1=${key});
return ".DescribeImagesResponse.imagesSet.item.imageId";
}
*/
struct ec2_map {
char *action;
struct grecs_list *args;
char *ret;
};
static struct grecs_keyword ec2_map_kw[] = {
{ "type", "'ec2", "Set map type",
grecs_type_null },
{ "key", "", "key expression",
grecs_type_null },
{ "action", NULL, "EC2 action",
grecs_type_string, GRECS_DFLT, NULL,
offsetof(struct ec2_map, action) },
{ "return", NULL, "return element",
grecs_type_string, GRECS_DFLT, NULL,
offsetof(struct ec2_map, ret) },
{ "arguments", NULL, "EC2 action",
grecs_type_string, GRECS_LIST, NULL,
offsetof(struct ec2_map, args) },
{ NULL }
};
static void
ec2_map_free(int dbg, void *data)
{
struct ec2_map *map = data;
free(map->action);
free(map->ret);
grecs_list_free(map->args);
free(map);
}
static void
ec2_map_confhelp()
{
static struct grecs_keyword ec2_map_top[] = {
{ "map", "name: string",
"Configuration for a EC2 map",
grecs_type_section, GRECS_INAC, NULL, 0, NULL, NULL,
ec2_map_kw },
{ NULL }
};
grecs_print_statement_array(ec2_map_top, 1, 0, stdout);
}
static int
ec2_map_config(int dbg, struct grecs_node *node, void *data)
{
int i;
int ec = 0;
struct ec2_map *map, **return_map = data;
map = grecs_zalloc(sizeof(*map));
for (i = 0; ec2_map_kw[i].ident; i++)
ec2_map_kw[i].varptr = map;
if (grecs_tree_process(node->down, ec2_map_kw)) {
ec2_map_free(dbg, map);
return eclat_map_failure;
}
if (!map->action) {
grecs_error(&node->locus, 0, "no action statement");
ec++;
}
if (!map->ret) {
grecs_error(&node->locus, 0, "no return statement");
ec++;
}
if (!map->args) {
grecs_error(&node->locus, 0, "no arguments statement");
ec++;
}
if (ec) {
ec2_map_free(dbg, map);
return eclat_map_failure;
}
*return_map = map;
return eclat_map_ok;
}
static int
ec2_map_open(int dbg, void *data)
{
return eclat_map_ok;
}
static int
ec2_map_close(int dbg, void *data)
{
return 0;
}
static int
ec2_map_get(int dbg, int dir, void *data, const char *key, char **return_value)
{
struct ec2_map *map = data;
struct ec2_request *q;
struct grecs_list_entry *ep;
struct wordsplit ws;
int wsflags;
char const *env[3];
struct grecs_node *tree, *node;
int rc;
q = eclat_request_create(use_ssl ? EC2_RF_HTTPS : 0, endpoint, "/",
region_name, access_key, security_token);
eclat_request_add_param(q, "Action", map->action);
env[0] = "key";
env[1] = key;
env[2] = NULL;
ws.ws_env = env;
ws.ws_error = err;
wsflags = WRDSF_NOSPLIT | WRDSF_NOCMD |
WRDSF_ENV | WRDSF_ENV_KV | WRDSF_WARNUNDEF | WRDSF_ERROR;
rc = 0;
for (ep = map->args->head; ep; ep = ep->next) {
char *p;
if (wordsplit((char *)ep->data, &ws, wsflags)) {
rc = 1;
break;
}
wsflags |= WRDSF_REUSE;
p = strchr(ws.ws_wordv[0], '=');
if (p) {
*p++ = 0;
eclat_request_add_param(q, ws.ws_wordv[0], p);
} else
eclat_request_add_param(q, ws.ws_wordv[0], "");
}
if (wsflags & WRDSF_REUSE)
wordsplit_free(&ws);
if (rc) {
eclat_request_free(q);
return eclat_map_failure;
}
if (eclat_send_request(q, &tree))
return eclat_map_failure;
node = grecs_find_node(tree, map->ret);
if (debug_category[dbg].level > 1) {
debug(dbg, 2, ("Got node:"));
grecs_print_node(node, GRECS_NODE_FLAG_DEFAULT, stderr);
fputc('\n', stderr);
}
rc = eclat_map_not_found;
if (node) {
if (node->type == grecs_node_stmt &&
node->v.value->type == GRECS_TYPE_STRING) {
*return_value = grecs_strdup(node->v.value->v.string);
rc = eclat_map_ok;
} else {
rc = eclat_map_failure;
}
}
grecs_tree_free(tree);
return rc;
}
struct eclat_map_drv eclat_map_drv_ec2 = {
"ec2",
ec2_map_config,
ec2_map_open,
ec2_map_close,
ec2_map_get,
ec2_map_free,
ec2_map_confhelp
};