finished table get rest api calls

This commit is contained in:
Bruce Potter 2014-03-18 18:47:01 -04:00
parent a5ff9cfeec
commit 0bd4753702
2 changed files with 173 additions and 32 deletions

View File

@ -549,13 +549,39 @@ my %URIdef = (
#### definition for database/table resources
table => {
table_nodes_allattr => {
desc => "[URI:/table/{table}/{noderange}] - The table resource",
matcher => '^\/table\/[^\/]*\/[^\/]*$',
table_nodes => {
desc => "[URI:/table/{tablelist}/node/{noderange}/{attrlist}] - The node table resource",
matcher => '^/table/[^/]+/node(/[^/]+){0,2}$',
GET => {
desc => "Get all the attibutes for noderange {noderange} of the table {table}.",
cmd => "getNodesAttribs",
fhandler => \&tablehdl,
desc => "Get attibutes for noderange {noderange} of the table {table}.",
cmd => "getTablesNodesAttribs", # not used
fhandler => \&tablenodehdl,
outhdler => \&tableout,
},
PUT => {
desc => "Change the attibutes for the table {table}.",
cmd => "chdef",
fhandler => \&defhdl,
#outhdler => \&defout,
},
POST => {
desc => "Create the table {table}. DataBody: {attr1:v1,att2:v2...}.",
cmd => "mkdef",
fhandler => \&defhdl,
},
DELETE => {
desc => "Remove the table {table}.",
cmd => "rmdef",
fhandler => \&defhdl,
},
},
table_rows => {
desc => "[URI:/table/{tablelist}/row/{keys}/{attrlist}] - The non-node table resource",
matcher => '^/table/[^/]+/row(/[^/]+){0,2}$',
GET => {
desc => "Get attibutes for rows of the table {table}.",
cmd => "getTablesAllRowAttribs", # not used
fhandler => \&tablerowhdl,
outhdler => \&tableout,
},
PUT => {
@ -775,7 +801,7 @@ if (defined ($URIdef{$uriLayer1})) {
foreach my $res (keys %{$URIdef{$uriLayer1}}) {
my $matcher = $URIdef{$uriLayer1}->{$res}->{matcher};
#bmp: if you use m|$matcher| here instead then you won't need to escape all of the /'s ?
if ($pathInfo =~ /$matcher/) {
if ($pathInfo =~ m|$matcher|) {
# matched to a resource
if (defined ($URIdef{$uriLayer1}->{$res}->{$requestType}->{fhandler})) { #bmp: if there isn't a handler, shouldn't we error out?
my $params;
@ -1090,22 +1116,52 @@ sub actionhdl {
}
# get all attrs of 1 table for a noderange
sub tablehdl {
# get attrs of tables for a noderange
sub tablenodehdl {
my $params = shift;
my @args;
my @urilayers = @{$params->{'layers'}};
# the array elements for @urilayers are:
# 0 - 'table'
# 1 - <tablelist>
# 2 - 'node'
# 3 - <noderange> (optional)
# 4 - <attrlist> (optional)
# set the command name
$request->{command} = $params->{'cmd'};
my @tables = split(/,/, $urilayers[1]);
# the uri is /table/<tablename>/<noderange>
if (defined($urilayers[1])) { $request->{table} = $urilayers[1]; }
if (defined($urilayers[2])) { $request->{noderange} = $urilayers[2]; }
if (!defined($urilayers[3]) || $urilayers[3] eq 'ALLNODES') {
$request->{command} = 'getTablesAllNodeAttribs';
} else {
$request->{command} = 'getTablesNodesAttribs';
$request->{noderange} = $urilayers[3];
}
# if they specified attrs, sort/group them by table
my $attrlist = $urilayers[4];
if (!defined($attrlist)) { $attrlist = 'ALL'; } # attr=ALL means get all non-blank attributes
my @attrs = split(/,/, $attrlist);
my %attrhash;
foreach my $a (@attrs) {
if ($a =~ /\./) {
my ($table, $attr) = split(/\./, $a);
push @{$attrhash{$table}}, $attr;
}
else { # the attr doesn't have a table qualifier so apply to all tables
foreach my $t (@tables) { push @{$attrhash{$t}}, $a; }
}
}
# deal with all of the tables and the attrs for each table
foreach my $tname (@tables) {
my $table = { tablename => $tname };
if (defined($attrhash{$tname})) { $table->{attr} = $attrhash{$tname}; }
else { $table->{attr} = 'ALL'; }
push @{$request->{table}}, $table;
}
# attr=ALL means get all non-blank attributes
$request->{attr} = 'ALL';
my $req = genRequest();
# disabling the KeyAttr option is important in this case, so xmlin doesn't pull the name attribute
@ -1115,22 +1171,104 @@ sub tablehdl {
return $responses;
}
# parse the output of all attrs of 1 table for a noderange
# get attrs of tables for keys
sub tablerowhdl {
my $params = shift;
my @args;
my @urilayers = @{$params->{'layers'}};
# the array elements for @urilayers are:
# 0 - 'table'
# 1 - <tablelist>
# 2 - 'row'
# 3 - <key-val-list> (optional)
# 4 - <attrlist> (optional)
# do stuff that is common between getAttribs and getTablesAllRowAttribs
my @tables = split(/,/, $urilayers[1]);
my $attrlist = $urilayers[4];
if (!defined($attrlist)) { $attrlist = 'ALL'; } # attr=ALL means get all non-blank attributes
my @attrs = split(/,/, $attrlist);
# get all rows for potentially multiple tables
if (!defined($urilayers[3]) || $urilayers[3] eq 'ALLROWS') {
$request->{command} = 'getTablesAllRowAttribs';
# if they specified attrs, sort/group them by table
my %attrhash;
foreach my $a (@attrs) {
if ($a =~ /\./) {
my ($table, $attr) = split(/\./, $a);
push @{$attrhash{$table}}, $attr;
}
else { # the attr doesn't have a table qualifier so apply to all tables
foreach my $t (@tables) { push @{$attrhash{$t}}, $a; }
}
}
# deal with all of the tables and the attrs for each table
foreach my $tname (@tables) {
my $table = { tablename => $tname };
if (defined($attrhash{$tname})) { $table->{attr} = $attrhash{$tname}; }
else { $table->{attr} = 'ALL'; }
push @{$request->{table}}, $table;
}
}
# for 1 table, get just one row based on the keys given
else {
if (scalar(@tables) > 1) { error('currently you can only specify keys for a single table.', $STATUS_BAD_REQUEST); }
$request->{command} = 'getAttribs';
$request->{table} = $tables[0];
if (defined($urilayers[3])) {
my @keyvals = split(/,/, $urilayers[3]);
foreach my $kv (@keyvals) {
my ($key, $value) = split(/\s*=\s*/, $kv, 2);
$request->{keys}->{$key} = $value;
}
}
foreach my $a (@attrs) { push @{$request->{attr}}, $a; }
}
my $req = genRequest();
# disabling the KeyAttr option is important in this case, so xmlin doesn't pull the name attribute
# out of the node hash and make it the key
my $responses = sendRequest($req, {SuppressEmpty => undef, ForceArray => 0, KeyAttr => []});
return $responses;
}
# parse the output of all attrs of tables. This is used for both node-oriented tables
# and non-node-oriented tables.
#todo: investigate a converter straight from xml to json
sub tableout {
my $data = shift;
my $json;
# For the table calls, we turn off ForceArray and KeyAttr for XMLin(), so the output is a little
# different than usual.
# each element is a hash with 1 key called "node" that has either: an array of node hashes,
my $json = {};
# For the table calls, we turned off ForceArray and KeyAttr for XMLin(), so the output is a little
# different than usual. Each element is a hash with key "table" that is either a hash or array of hashes.
# Each element of that is a hash with 2 keys called "tablename" and "node". The latter has either: an array of node hashes,
# or (if there is only 1 node returned) the node hash directly.
# We are producing json that is a hash of table name keys that each have an array of node objects.
foreach my $d (@$data) {
my $jsonnode = $d->{node};
#debug(Dumper($d)); debug (Dumper($jsonnode));
if (ref($jsonnode) eq 'HASH') { push @$json, $jsonnode; } # 1 node
elsif (ref($jsonnode) eq 'ARRAY') { # an array of nodes
foreach my $n (@$jsonnode) { push @$json, $n; }
my $table = $d->{table};
if (!defined($table)) { # special case for the getAttribs cmd
$json = $d;
last;
}
#debug(Dumper($d)); debug (Dumper($jsonnode));
if (ref($table) eq 'HASH') { $table = [$table]; } # if a single table, make it a 1 element array of tables
foreach my $t (@$table) {
my $jsonnodes = []; # start an array of node objects for this table
my $tabname = $t->{tablename};
if (!defined($tabname)) { $tabname = 'unknown' . $::i++; } #todo: have lissa fix this bug
$json->{$tabname} = $jsonnodes; # add it into the top level hash
my $node = $t->{node};
if (!defined($node)) { $node = $t->{row}; }
#debug(Dumper($d)); debug (Dumper($jsonnode));
if (ref($node) eq 'HASH') { $node = [$node]; } # if a single node, make it a 1 element array of nodes
foreach my $n (@$node) { push @$jsonnodes, $n; }
}
else { error('improperly formatted output from xcatd', $STATUS_TEAPOT); }
}
addPageContent($JSON->encode($json));
}
@ -1162,18 +1300,20 @@ sub displayUsage {
#bmp: is there a way to avoid make a copy of the whole response? For big output that could be time consuming.
# For the error tag, you don't have to bother copying the response, because you are going to exit anyway.
# Maybe this function could just verify there is a serverdone and handle any error, and then
# let the output handler ignore the serverdone tag?
# let each specific output handler ignore the serverdone tag?
sub filterData {
my $data = shift;
my $errorInformation = '';
#debugandexit(Dumper($data));
my $outputdata;
#trim the serverdone message off
foreach (@{$data}) {
if (exists($_->{serverdone}) || defined($_->{error})) {
if (exists($_->{serverdone}) && defined($_->{error})) {
$errorInformation = $_->{error}->[0];
addPageContent($q->p($errorInformation));
if (ref($_->{error}) eq 'ARRAY') { $errorInformation = $_->{error}->[0]; }
else { $errorInformation = $_->{error}; }
addPageContent(qq({"error":"$errorInformation"}));
if (($errorInformation =~ /Permission denied/) || ($errorInformation =~ /Authentication failure/)) {
sendResponseMsg($STATUS_UNAUTH);
}
@ -1358,6 +1498,7 @@ sub sendResponseMsg {
$tempFormat = 'text/html';
}
print $q->header(-status => $code, -type => $tempFormat);
if ($pageContent) { $pageContent .= "\n"; } # if there is any content, append a newline
print $pageContent;
exit(0);
}
@ -1540,7 +1681,7 @@ sub error {
my $m;
#if ($format eq 'xml') { $m = "<$severity>$msg</$severity>\n"; }
#elsif ($format eq 'json') {
$m = qq({"$severity":"$msg"}\n);
$m = qq({"$severity":"$msg"});
#}
#else { $m = "<p>$severity: $msg</p>\n"; }
addPageContent($m);
@ -1556,7 +1697,7 @@ sub debug {
# when having bugs that cause this cgi to not produce any output, output something and then exit.
sub debugandexit {
addPageContent("$_[0]\n");
debug("$_[0]\n");
sendResponseMsg($STATUS_OK);
}

View File

@ -117,7 +117,7 @@ curl -# -X POST -k "https://127.0.0.1/xcatws/node/$nr/dcp?userName=$user&passwor
| grep -q '"errorcode":"0"'; chkrc
# test the table calls
#curl -# -X GET -k "https://127.0.0.1/xcatws/table/nodelist/test001?userName=$user&password=$pw&$format"
curl -# -X GET -k "https://127.0.0.1/xcatws/table/nodelist/wstest?userName=$user&password=$pw&$format"
exit