aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--etc/Makefile.am1
-rw-r--r--etc/describe-security-groups.fln59
-rw-r--r--lib/forlan.c170
-rw-r--r--lib/forlan.h5
-rw-r--r--lib/forlangrm.y15
-rw-r--r--lib/forlanlex.l2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/cretags.c2
-rw-r--r--src/deltags.c1
-rw-r--r--src/dscrsecgrps-cl.opt37
-rw-r--r--src/dscrsecgrps.c35
-rw-r--r--src/eclat.c4
-rw-r--r--src/eclat.h1
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/describe-security-groups.at82
-rw-r--r--tests/testsuite.at1
16 files changed, 366 insertions, 52 deletions
diff --git a/etc/Makefile.am b/etc/Makefile.am
index 514993c..3ccb0f4 100644
--- a/etc/Makefile.am
+++ b/etc/Makefile.am
@@ -24,6 +24,7 @@ FLNFILES=\
describe-instance-attribute.fln\
describe-instance-status.fln\
describe-instances.fln\
+ describe-security-groups.fln\
describe-tags.fln\
describe-volumes.fln\
disassociate-address.fln\
diff --git a/etc/describe-security-groups.fln b/etc/describe-security-groups.fln
new file mode 100644
index 0000000..55e2921
--- /dev/null
+++ b/etc/describe-security-groups.fln
@@ -0,0 +1,59 @@
+/* This file is part of Eclat.
+ Copyright (C) 2012 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 <http://www.gnu.org/licenses/>. */
+
+if (.DescribeSecurityGroupsResponse.securityGroupInfo) {
+ for (grp in .DescribeSecurityGroupsResponse.securityGroupInfo.item) {
+ print("Group ", grp.groupId,"\t", grp.groupName, "\t",
+ grp.groupDescription, "\n");
+ print("VPC ID: ", grp.vpcId, "\n");
+ for (var in grp.tagSet.item) {
+ print("TAG ", var.key, "\t", var.value, "\n");
+ }
+ print("Incoming:\n");
+ for (var in grp.ipPermissions.item) {
+ for (range in var.ipRanges.item) {
+ print(var.ipProtocol,"\t",range.cidrIp,"\t",var.fromPort);
+ if (var.fromPort != var.toPort)
+ print("-",var.toPort);
+ print("\n");
+ }
+ for (usr in var.groups.item) {
+ print("user ", usr.userId, ", group ", usr.groupId, " (", usr.groupName,
+ ")\t", var.fromPort);
+ if (var.fromPort != var.toPort)
+ print("-",var.toPort);
+ print("\n");
+ }
+ }
+
+ print("Outgoing:\n");
+ for (var in grp.ipPermissionsEgress.item) {
+ for (range in var.ipRanges.item) {
+ print(var.ipProtocol,"\t",range.cidrIp,"\t",var.fromPort);
+ if (var.fromPort != var.toPort)
+ print("-",var.toPort);
+ print("\n");
+ }
+ for (usr in var.groups.item) {
+ print("user ", usr.userId, ", group ", usr.groupId, " (", usr.groupName,
+ ")\t", var.fromPort);
+ if (var.fromPort != var.toPort)
+ print("-",var.toPort);
+ print("\n");
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/lib/forlan.c b/lib/forlan.c
index 74b03a3..f1d49d7 100644
--- a/lib/forlan.c
+++ b/lib/forlan.c
@@ -97,103 +97,161 @@ valtypestr(enum forlan_value_type t)
}
}
-static void
-coerce_retval(forlan_eval_env_t env, int c)
+static int
+value_boolean(struct forlan_value *val)
{
- enum forlan_value_type t;
- struct grecs_node *node;
+ int res;
- switch (c) {
- case 's':
- t = forlan_value_literal;
+ switch (val->type) {
+ case forlan_value_void:
+ err("controlling expression returned void, aborting");
+ abort();
+
+ case forlan_value_node:
+ res = val->v.node != NULL;
break;
- case 'n':
- t = forlan_value_node;
+
+ case forlan_value_literal:
+ res = val->v.string != NULL && val->v.string[0] != 0;
break;
- case 'b':
- t = forlan_value_boolean;
+
+ case forlan_value_boolean:
+ res = val->v.num;
break;
- case ' ':
- t = forlan_value_void;
+
+ default:
+ abort();
}
+ return res;
+}
+
+int
+retval_boolean(forlan_eval_env_t env)
+{
+ return value_boolean(&env->retval);
+}
- if (t == env->retval.type)
+static void
+coerce_value(forlan_eval_env_t env, struct forlan_value *val,
+ enum forlan_value_type t)
+{
+ struct grecs_node *node;
+
+ if (t == val->type)
return;
if (t == forlan_value_void) {
- free_value(&env->retval);
- env->retval.type = forlan_value_void;
+ free_value(val);
+ val->type = forlan_value_void;
return;
}
- if (env->retval.type == forlan_value_void) {
+ if (val->type == forlan_value_void) {
err("can't coerce %s to %s",
- valtypestr(env->retval.type),
+ valtypestr(val->type),
valtypestr(t));
abort();
}
if (t == forlan_value_boolean) {
- int res = retval_boolean(env);
- free_value(&env->retval);
- env->retval.type = forlan_value_boolean;
- env->retval.v.num = res;
+ int res = value_boolean(val);
+ free_value(val);
+ val->type = forlan_value_boolean;
+ val->v.num = res;
return;
}
/* Convert between string and node */
- switch (env->retval.type) {
+ switch (val->type) {
case forlan_value_literal:
- node = grecs_find_node(env->tree, env->retval.v.string);
- free(env->retval.v.string);
- env->retval.v.node = node;
+ node = grecs_find_node(env->tree, val->v.string);
+ free(val->v.string);
+ val->v.node = node;
break;
case forlan_value_node:
- if (env->retval.v.node->type == grecs_node_stmt) {
+ if (val->v.node->type == grecs_node_stmt) {
struct grecs_txtacc *acc = grecs_txtacc_create();
- grecs_txtacc_format_value(env->retval.v.node->v.value,
+ grecs_txtacc_format_value(val->v.node->v.value,
0, acc);
- env->retval.v.string = grecs_txtacc_finish(acc, 1);
+ grecs_txtacc_grow_char(acc, 0);
+ val->v.string = grecs_txtacc_finish(acc, 1);
grecs_txtacc_free(acc);
} else
- env->retval.v.string = grecs_strdup("");
+ val->v.string = grecs_strdup("");
break;
default:
abort();
}
- env->retval.type = t;
+ val->type = t;
}
+
+static void
+coerce_retval(forlan_eval_env_t env, int c)
+{
+ enum forlan_value_type t;
+
+ switch (c) {
+ case 's':
+ t = forlan_value_literal;
+ break;
+ case 'n':
+ t = forlan_value_node;
+ break;
+ case 'b':
+ t = forlan_value_boolean;
+ break;
+ case ' ':
+ t = forlan_value_void;
+ }
+ coerce_value(env, &env->retval, t);
+}
+
+#define T_E -1
+#define T_V forlan_value_void
+#define T_N forlan_value_node
+#define T_S forlan_value_literal
+#define T_B forlan_value_boolean
+
+enum forlan_value_type convtab[FORLAN_NTYPES][FORLAN_NTYPES] = {
+ /* T_V T_N T_S T_B */
+/* T_V */ { T_E, T_E, T_E, T_E },
+/* T_N */ { T_E, T_S, T_S, T_B },
+/* T_S */ { T_E, T_S, T_S, T_B },
+/* T_B */ { T_E, T_B, T_B, T_B }
+};
-int
-retval_boolean(forlan_eval_env_t env)
+static int
+values_equal(forlan_eval_env_t env,
+ struct forlan_value *a, struct forlan_value *b)
{
int res;
-
- switch (env->retval.type) {
- case forlan_value_void:
- err("controlling expression returned void, aborting");
- abort();
+ enum forlan_value_type t;
- case forlan_value_node:
- res = env->retval.v.node != NULL;
- break;
+ t = convtab[a->type][b->type];
+ if (t == T_E) {
+ err("incompatible values for comparison: %s, %s",
+ valtypestr(a->type),
+ valtypestr(b->type));
+ abort();
+ }
+ coerce_value(env, a, t);
+ coerce_value(env, b, t);
- case forlan_value_literal:
- res = env->retval.v.string != NULL &&
- env->retval.v.string[0] != 0;
+ switch (t) {
+ case T_S:
+ res = strcmp(a->v.string, b->v.string) == 0;
break;
-
- case forlan_value_boolean:
- res = env->retval.v.num;
+ case T_B:
+ res = !!a->v.num == !!b->v.num;
break;
-
default:
abort();
}
return res;
}
+
void eval_func(forlan_eval_env_t env, union forlan_node *node);
void eval_last(forlan_eval_env_t env, union forlan_node *node);
@@ -460,6 +518,7 @@ void
eval_expr(forlan_eval_env_t env, union forlan_node *node)
{
int res;
+ struct forlan_value lval;
free_value(&env->retval);
switch (node->expr.opcode) {
@@ -486,7 +545,20 @@ eval_expr(forlan_eval_env_t env, union forlan_node *node)
env->retval.type = forlan_value_boolean;
env->retval.v.num = !res;
break;
-
+
+ case forlan_opcode_eq:
+ case forlan_opcode_ne:
+ forlan_eval(env, node->expr.arg[0]);
+ copy_value(&lval, &env->retval);
+ forlan_eval(env, node->expr.arg[1]);
+ res = values_equal(env, &lval, &env->retval);
+ free_value(&lval);
+ free_value(&env->retval);
+ env->retval.type = forlan_value_boolean;
+ env->retval.v.num = node->expr.opcode == forlan_opcode_eq ?
+ res : !res;
+ break;
+
default:
abort();
}
diff --git a/lib/forlan.h b/lib/forlan.h
index 424cea8..0670480 100644
--- a/lib/forlan.h
+++ b/lib/forlan.h
@@ -123,7 +123,9 @@ enum forlan_opcode {
forlan_opcode_node, /* Evaluate node, set 'last' */
forlan_opcode_and, /* Boolean AND */
forlan_opcode_or, /* Boolean OR */
- forlan_opcode_not /* Boolean NOT */
+ forlan_opcode_not, /* Boolean NOT */
+ forlan_opcode_eq, /* Equality */
+ forlan_opcode_ne /* Inequality */
};
/* Boolean expression */
@@ -164,6 +166,7 @@ enum forlan_value_type {
forlan_value_literal,
forlan_value_boolean
};
+#define FORLAN_NTYPES 4
struct forlan_value {
enum forlan_value_type type;
diff --git a/lib/forlangrm.y b/lib/forlangrm.y
index eb7fc6f..5c91f1a 100644
--- a/lib/forlangrm.y
+++ b/lib/forlangrm.y
@@ -64,6 +64,7 @@ free_comp(void *p)
%left OR
%left AND
+%nonassoc EQ NE
%left NOT
%type <node> stmt stmt_cond stmt_expr stmt_blk cond bool node funcall arg rval
@@ -152,6 +153,20 @@ bool : node
$$->expr.opcode = forlan_opcode_not;
$$->expr.arg[0] = $2;
}
+ | node EQ node
+ {
+ $$ = forlan_node_create(forlan_type_expr);
+ $$->expr.opcode = forlan_opcode_eq;
+ $$->expr.arg[0] = $1;
+ $$->expr.arg[1] = $3;
+ }
+ | node NE node
+ {
+ $$ = forlan_node_create(forlan_type_expr);
+ $$->expr.opcode = forlan_opcode_ne;
+ $$->expr.arg[0] = $1;
+ $$->expr.arg[1] = $3;
+ }
| '(' bool ')'
{
$$ = $2;
diff --git a/lib/forlanlex.l b/lib/forlanlex.l
index 8b3d29a..8df6d80 100644
--- a/lib/forlanlex.l
+++ b/lib/forlanlex.l
@@ -83,6 +83,8 @@ continue return CONTINUE;
! return NOT;
"&&" return AND;
"||" return OR;
+"==" return EQ;
+"!=" return NE;
{IDC}{IDC}* { grecs_line_begin();
grecs_line_add(yytext, yyleng);
yylval.string = grecs_line_finish();
diff --git a/src/Makefile.am b/src/Makefile.am
index de1c17b..1f533ef 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,6 +29,7 @@ eclat_SOURCES=\
dscrinstattr.c\
dscrinsts.c\
dscrinststat.c\
+ dscrsecgrps.c\
dscrvols.c\
eclat.c\
eclat.h\
@@ -50,6 +51,7 @@ OPTFILES=\
disassaddr-cl.opt\
dscraddrs-cl.opt\
dscrinststat-cl.opt\
+ dscrsecgrps-cl.opt\
generic-cl.opt
eclat_SOURCES += $(OPTFILES:.opt=.h)
diff --git a/src/cretags.c b/src/cretags.c
index 1831839..b46d02a 100644
--- a/src/cretags.c
+++ b/src/cretags.c
@@ -49,7 +49,7 @@ eclat_create_tags(CURL *curl, int argc, char **argv)
grecs_asprintf(&bufptr, &bufsize, "Tag.%d.Value", rno);
eclat_query_add_param(q, bufptr, argv[i + 2]);
}
-
+ free(bufptr);
return eclat_send_query(curl, q);
}
diff --git a/src/deltags.c b/src/deltags.c
index 924d94d..e599570 100644
--- a/src/deltags.c
+++ b/src/deltags.c
@@ -55,6 +55,7 @@ eclat_delete_tags(CURL *curl, int argc, char **argv)
eclat_query_add_param(q, bufptr, p);
}
}
+ free(bufptr);
return eclat_send_query(curl, q);
}
diff --git a/src/dscrsecgrps-cl.opt b/src/dscrsecgrps-cl.opt
new file mode 100644
index 0000000..9aa657d
--- /dev/null
+++ b/src/dscrsecgrps-cl.opt
@@ -0,0 +1,37 @@
+/* This file is part of Eclat.
+ Copyright (C) 2012 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 <http://www.gnu.org/licenses/>. */
+
+OPTIONS_BEGIN("eclat describe-security-groups",
+ [<returns information about security groups>],
+ [<[FILTER...]>],
+ [<gnu>],
+ [<nousage>],
+ [<noversion>])
+
+OPTION(group-name,n,,
+ [<treat non-filter arguments as group names, instead of group IDs>])
+BEGIN
+ name_option = 1;
+END
+
+OPTIONS_END
+
+static void
+parse_options(int argc, char *argv[], int *index)
+{
+ GETOPT(argc, argv, *index, exit(EX_USAGE))
+}
+
diff --git a/src/dscrsecgrps.c b/src/dscrsecgrps.c
new file mode 100644
index 0000000..7049ddb
--- /dev/null
+++ b/src/dscrsecgrps.c
@@ -0,0 +1,35 @@
+/* This file is part of Eclat.
+ Copyright (C) 2012 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 <http://www.gnu.org/licenses/>. */
+
+#include "eclat.h"
+static int name_option;
+#include "dscrsecgrps-cl.h"
+
+int
+eclat_describe_security_groups(CURL *curl, int argc, char **argv)
+{
+ int i;
+ struct ec2_query *q;
+
+ parse_options(argc, argv, &i);
+ argv += i;
+ argc -= i;
+
+ q = describe_query_create(curl, "DescribeSecurityGroups", argc, argv,
+ name_option ? "GroupName" : "GroupId");
+ return eclat_send_query(curl, q);
+}
+
diff --git a/src/eclat.c b/src/eclat.c
index 2b0047e..f229e77 100644
--- a/src/eclat.c
+++ b/src/eclat.c
@@ -244,7 +244,9 @@ struct command cmdtab[] = {
{ "delete-tags", "DeleteTags",
eclat_delete_tags },
{ "get-console-output", "GetConsoleOutput",
- eclat_get_console_output }
+ eclat_get_console_output },
+ { "describe-security-groups", "DescribeSecurityGroups",
+ eclat_describe_security_groups }
};
size_t cmdcnt = sizeof(cmdtab) / sizeof(cmdtab[0]);
diff --git a/src/eclat.h b/src/eclat.h
index 8d488f9..a82a28a 100644
--- a/src/eclat.h
+++ b/src/eclat.h
@@ -71,6 +71,7 @@ int eclat_get_console_output(CURL *curl, int argc, char **argv);
int eclat_describe_instance_attribute(CURL *curl, int argc, char **argv);
int eclat_create_tags(CURL *curl, int argc, char **argv);
int eclat_delete_tags(CURL *curl, int argc, char **argv);
+int eclat_describe_security_groups(CURL *curl, int argc, char **argv);
char *region_to_endpoint(const char *region);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index c03730f..abe8f98 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -46,6 +46,7 @@ TESTSUITE_AT = \
describe-instance-attribute.at\
describe-instance-status.at\
describe-instances.at\
+ describe-security-groups.at\
describe-tags.at\
describe-volumes.at\
dump01.at\
diff --git a/tests/describe-security-groups.at b/tests/describe-security-groups.at
new file mode 100644
index 0000000..4b424d8
--- /dev/null
+++ b/tests/describe-security-groups.at
@@ -0,0 +1,82 @@
+# This file is part of Eclat -*- Autotest -*-
+# Copyright (C) 2012 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 <http://www.gnu.org/licenses/>.
+
+ECLAT_TEST_FORMAT([DescribeSecurityGroups],
+[DescribeSecurityGroups],
+[describe-security-groups.fln],
+[<DescribeSecurityGroupsResponse xmlns="http://ec2.amazonaws.com/doc/2012-08-15/">
+ <requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
+ <securityGroupInfo>
+ <item>
+ <ownerId>111122223333</ownerId>
+ <groupId>sg-443d0a12</groupId>
+ <groupName>WebServers</groupName>
+ <groupDescription>Web Servers</groupDescription>
+ <vpcId/>
+ <ipPermissions>
+ <item>
+ <ipProtocol>tcp</ipProtocol>
+ <fromPort>80</fromPort>
+ <toPort>80</toPort>
+ <groups/>
+ <ipRanges>
+ <item>
+ <cidrIp>0.0.0.0/0</cidrIp>
+ </item>
+ </ipRanges>
+ </item>
+ </ipPermissions>
+ <ipPermissionsEgress/>
+ <tagSet/>
+ </item>
+ <item>
+ <ownerId>111122223333</ownerId>
+ <groupId>sg-5ff8a023</groupId>
+ <groupName>RangedPortsBySource</groupName>
+ <groupDescription>Group A</groupDescription>
+ <ipPermissions>
+ <item>
+ <ipProtocol>tcp</ipProtocol>
+ <fromPort>6000</fromPort>
+ <toPort>7000</toPort>
+ <groups>
+ <item>
+ <userId>111122223333</userId>
+ <groupId>sg-99gh4012</groupId>
+ <groupName>Group B</groupName>
+ </item>
+ </groups>
+ <ipRanges/>
+ </item>
+ </ipPermissions>
+ <ipPermissionsEgress/>
+ <tagSet/>
+ </item>
+ </securityGroupInfo>
+</DescribeSecurityGroupsResponse>
+],
+[Group sg-443d0a12 WebServers "Web Servers"
+VPC ID:
+Incoming:
+tcp 0.0.0.0/0 80
+Outgoing:
+Group sg-5ff8a023 RangedPortsBySource "Group A"
+VPC ID:
+Incoming:
+user 111122223333, group sg-99gh4012 ("Group B") 6000-7000
+Outgoing:
+])
+
diff --git a/tests/testsuite.at b/tests/testsuite.at
index b47591f..c740e1f 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -60,6 +60,7 @@ m4_include([describe-addresses.at])
m4_include([describe-instance-attribute.at])
m4_include([describe-instance-status.at])
m4_include([describe-instances.at])
+m4_include([describe-security-groups.at])
m4_include([describe-tags.at])
m4_include([describe-volumes.at])
m4_include([get-console-output.at])

Return to:

Send suggestions and report system problems to the System administrator.