/* This file is part of Eclat. Copyright (C) 2012-2014 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; struct eclat_io *io; }; 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; eclat_io_free(map->io); 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) { struct ec2_map *map = data; map->io = eclat_io_init(0); if (!map->io) { err("cannot open EC2 database"); return eclat_map_failure; } return eclat_map_ok; } static int ec2_map_close(int dbg, void *data) { struct ec2_map *map = data; eclat_io_free(map->io); map->io = NULL; 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_query *q; struct grecs_list_entry *ep; struct wordsplit ws; int wsflags; char const *env[3]; struct grecs_node *tree, *node; int rc; q = eclat_query_create(use_ssl ? EC2_QF_HTTPS : 0, endpoint, "/"); eclat_query_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_query_add_param(q, ws.ws_wordv[0], p); } else eclat_query_add_param(q, ws.ws_wordv[0], ""); } if (wsflags & WRDSF_REUSE) wordsplit_free(&ws); if (rc) { eclat_query_free(q); return eclat_map_failure; } rc = eclat_send_query(map->io->curl, q); if (rc) return eclat_map_failure; tree = eclat_io_finish(map->io); 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 };