You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by mi...@apache.org on 2017/05/24 02:40:08 UTC
[03/14] incubator-trafficcontrol git commit: Adding capabilities &
api_capalities APIs
Adding capabilities & api_capalities APIs
(cherry picked from commit db31205f6cdae581f072a34347f057441721b31c)
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/9546e8ad
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/9546e8ad
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/9546e8ad
Branch: refs/heads/master
Commit: 9546e8ad26fac8a221880867a5e62f00cf9cbbf2
Parents: 5392f50
Author: naamashoresh <na...@qwilt.com>
Authored: Thu May 4 10:28:18 2017 +0300
Committer: Jeremy Mitchell <mi...@gmail.com>
Committed: Tue May 23 20:39:02 2017 -0600
----------------------------------------------------------------------
traffic_ops/app/lib/API/ApiCapability.pm | 258 ++++++++++++++++++++++++++
traffic_ops/app/lib/API/Capability.pm | 185 ++++++++++++++++++
traffic_ops/app/lib/TrafficOpsRoutes.pm | 17 ++
3 files changed, 460 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/9546e8ad/traffic_ops/app/lib/API/ApiCapability.pm
----------------------------------------------------------------------
diff --git a/traffic_ops/app/lib/API/ApiCapability.pm b/traffic_ops/app/lib/API/ApiCapability.pm
new file mode 100644
index 0000000..2e2ca73
--- /dev/null
+++ b/traffic_ops/app/lib/API/ApiCapability.pm
@@ -0,0 +1,258 @@
+package API::ApiCapability;
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+
+use UI::Utils;
+
+use Mojo::Base 'Mojolicious::Controller';
+use Data::Dumper;
+
+
+
+my $finfo = __FILE__ . ":";
+
+my %valid_http_methods = map { $_ => 1 } ('GET', 'POST', 'PUT', 'PATCH', 'DELETE');
+
+sub all {
+ my $self = shift;
+ my @data;
+ my $orderby = "capability";
+ $orderby = $self->param('orderby') if ( defined $self->param('orderby') );
+
+ my $rs_data = $self->db->resultset("ApiCapability")->search( undef, { order_by => $orderby } );
+ while ( my $row = $rs_data->next ) {
+ push(
+ @data, {
+ "id" => $row->id,
+ "httpMethod" => $row->http_method,
+ "route" => $row->route,
+ "capName" => $row->capability->name,
+ "lastUpdated" => $row->last_updated
+ }
+ );
+ }
+ $self->success( \@data );
+}
+
+
+sub renderResults {
+ my $self = shift;
+ my $rs_data = shift;
+
+ my @data = ();
+ while ( my $row = $rs_data->next ) {
+ push(
+ @data, {
+ "id" => $row->id,
+ "httpMethod" => $row->http_method,
+ "route" => $row->route,
+ "capName" => $row->capability->name,
+ "lastUpdated" => $row->last_updated
+ }
+ );
+ }
+ $self->success( \@data );
+}
+
+sub capName {
+ my $self = shift;
+ my $capability = $self->param('name');
+
+ my $rs_data = $self->db->resultset("ApiCapability")->search( 'me.capability' => $capability );
+ $self->renderResults( $rs_data ) ;
+}
+
+sub index {
+ my $self = shift;
+ my $id = $self->param('id');
+
+ my $rs_data = $self->db->resultset("ApiCapability")->search( 'me.id' => $id );
+ $self->renderResults( $rs_data ) ;
+}
+
+sub is_mapping_valid {
+ my $self = shift;
+ my $id = shift;
+ my $http_method = shift;
+ my $route = shift;
+ my $capability = shift;
+
+ if ( !defined($http_method) ) {
+ return ( undef, "HTTP method is required." );
+ }
+
+ if ( !exists( $valid_http_methods{ $http_method } ) ) {
+ return ( undef, "HTTP method \'$http_method\' is invalid. Valid values are: " . join(", ", sort keys %valid_http_methods ) );
+ }
+
+ if ( !defined($route) or $route eq "" ) {
+ return ( undef, "Route is required." );
+ }
+
+ if ( !defined($capability) or $capability eq "" ) {
+ return (undef, "Capability name is required." );
+ }
+ # check if capability exists
+ my $rs_data = $self->db->resultset("Capability")->search( { 'name' => { 'like', $capability } } )->single();
+ if (!defined($rs_data)) {
+ return (undef, "Capability '$capability' does not exist." );
+ }
+
+ # search a mapping for the same http_method & route
+ $rs_data = $self->db->resultset("ApiCapability")->search( { 'route' => { 'like', $route } } )->search( {
+ 'http_method' => { '=', $http_method } } )->single();
+ # if adding a new entry, make sure it is unique
+ if ( !defined( $id ) ) {
+ if (defined($rs_data)) {
+ my $allocated_capability = $rs_data->capability->name;
+ return (undef, "HTTP method '$http_method', route '$route' are already mapped to capability: $allocated_capability" );
+ }
+ }
+ else {
+ if (defined($rs_data)) {
+ my $lid = $rs_data->id;
+ if ($lid ne $id) {
+ my $allocated_capability = $rs_data->capability->name;
+ return (undef, "HTTP method '$http_method', route '$route' are already mapped to capability: $allocated_capability" );
+ }
+ }
+ }
+
+ return ( 1, undef );
+}
+
+sub create {
+ my $self = shift;
+ my $params = $self->req->json;
+
+ if ( !&is_oper($self) ) {
+ return $self->forbidden();
+ }
+
+ if ( !defined($params) ) {
+ return $self->alert("Parameters must be in JSON format.");
+ }
+
+ my $http_method = $params->{httpMethod} if defined($params->{httpMethod});
+ my $route = $params->{route} if defined($params->{route});
+ my $capability = $params->{capName} if defined($params->{capName});
+ my $id = undef;
+
+ my ( $is_valid, $errStr ) = $self->is_mapping_valid( $id, $http_method, $route, $capability );
+ if ( !$is_valid ) {
+ return $self->alert( $errStr );
+ }
+
+ my $values = {
+ id => $self->db->resultset('ApiCapability')->get_column('id')->max() + 1,
+ http_method => $http_method,
+ route => $route,
+ capability => $capability
+ };
+
+ my $insert = $self->db->resultset('ApiCapability')->create($values);
+ my $rs = $insert->insert();
+ if ($rs) {
+ my $response;
+ $response->{id} = $rs->id;
+ $response->{httpMethod} = $rs->http_method;
+ $response->{route} = $rs->route;
+ $response->{capName} = $rs->capability->name;
+ $response->{lastUpdated} = $rs->last_updated;
+
+ &log( $self, "Created API-Capability mapping: '$response->{httpMethod}', '$response->{route}', '$response->{capName}' for id: " . $response->{id}, "APICHANGE" );
+
+ return $self->success( $response, "API-Capability mapping was created." );
+ }
+ else {
+ return $self->alert( "API-Capability mapping creation failed." );
+ }
+}
+
+sub update {
+ my $self = shift;
+ my $id = $self->param('id');
+ my $params = $self->req->json;
+
+ if ( !&is_oper($self) ) {
+ return $self->forbidden();
+ }
+
+ if ( !defined($params) ) {
+ return $self->alert("Parameters must be in JSON format.");
+ }
+
+ my $http_method = $params->{httpMethod} if defined($params->{httpMethod});
+ my $route = $params->{route} if defined($params->{route});
+ my $capability = $params->{capName} if defined($params->{capName});
+
+ my $mapping = $self->db->resultset('ApiCapability')->find( { id => $id } );
+ if ( !defined($mapping) ) {
+ return $self->not_found();
+ }
+
+ my ( $is_valid, $errStr ) = $self->is_mapping_valid( $id, $http_method, $route, $capability );
+ if ( !$is_valid ) {
+ return $self->alert( $errStr );
+ }
+
+ my $values = {
+ http_method => $http_method,
+ route => $route,
+ capability => $capability
+ };
+
+ my $rs = $mapping->update($values);
+ if ($rs) {
+ my $response;
+ $response->{id} = $rs->id;
+ $response->{httpMethod} = $rs->http_method;
+ $response->{route} = $rs->route;
+ $response->{capName} = $rs->capability->name;
+ $response->{lastUpdated} = $rs->last_updated;
+
+ &log( $self, "Updated API-Capability mapping: '$response->{httpMethod}', '$response->{route}', '$response->{capName}' for id: " . $response->{id}, "APICHANGE" );
+
+ return $self->success( $response, "API-Capability mapping was updated." );
+ }
+ else {
+ return $self->alert( "API-Capability mapping update failed." );
+ }
+}
+
+sub delete {
+ my $self = shift;
+ my $id = $self->param('id');
+
+ if ( !&is_oper($self) ) {
+ return $self->forbidden();
+ }
+
+ my $mapping = $self->db->resultset('ApiCapability')->find( { id => $id } );
+ if ( !defined($mapping) ) {
+ return $self->not_found();
+ }
+
+ my $rs = $mapping->delete();
+ if ($rs) {
+ return $self->success_message("API-capability mapping deleted.");
+ } else {
+ return $self->alert( "API-capability mapping deletion failed." );
+ }
+}
+
+1;
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/9546e8ad/traffic_ops/app/lib/API/Capability.pm
----------------------------------------------------------------------
diff --git a/traffic_ops/app/lib/API/Capability.pm b/traffic_ops/app/lib/API/Capability.pm
new file mode 100644
index 0000000..695434b
--- /dev/null
+++ b/traffic_ops/app/lib/API/Capability.pm
@@ -0,0 +1,185 @@
+package API::Capability;
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+
+use UI::Utils;
+
+use Mojo::Base 'Mojolicious::Controller';
+use Data::Dumper;
+
+my $finfo = __FILE__ . ":";
+
+sub all {
+ my $self = shift;
+ my @data;
+ my $orderby = "name";
+ $orderby = $self->param('orderby') if ( defined $self->param('orderby') );
+
+ my $rs_data = $self->db->resultset("Capability")->search( undef, { order_by => $orderby } );
+ while ( my $row = $rs_data->next ) {
+ push(
+ @data, {
+ "name" => $row->name,
+ "description" => $row->description,
+ "lastUpdated" => $row->last_updated
+ }
+ );
+ }
+ $self->success( \@data );
+}
+
+sub name {
+ my $self = shift;
+ my $name = $self->param('name');
+
+ my $rs_data = $self->db->resultset("Capability")->search( 'me.name' => $name );
+ my @data = ();
+ while ( my $row = $rs_data->next ) {
+ push(
+ @data, {
+ "name" => $row->name,
+ "description" => $row->description,
+ "lastUpdated" => $row->last_updated
+ }
+ );
+ }
+ $self->success( \@data );
+}
+
+sub create {
+ my $self = shift;
+ my $params = $self->req->json;
+
+ if ( !&is_oper($self) ) {
+ return $self->forbidden();
+ }
+
+ if ( !defined($params) ) {
+ return $self->alert("Parameters must be in JSON format.");
+ }
+
+ my $name = $params->{name} if defined($params->{name});
+ my $description = $params->{description} if defined($params->{description});
+
+ if ( !defined($name) or $name eq "" ) {
+ return $self->alert( "Name is required." );
+ }
+
+ if ( !defined($description) or $description eq "" ) {
+ return $self->alert( "Description is required." );
+ }
+
+ # check if capability exists
+ my $rs_data = $self->db->resultset("Capability")->search( { 'name' => { 'like', $name } } )->single();
+ if (defined($rs_data)) {
+ return $self->alert( "Capability '$name' already exists." );
+ }
+
+ my $values = {
+ name => $name,
+ description => $description
+ };
+
+ my $insert = $self->db->resultset('Capability')->create($values);
+ my $rs = $insert->insert();
+ if ($rs) {
+ my $response;
+ $response->{name} = $rs->name;
+ $response->{description} = $rs->description;
+
+ &log( $self, "Created Capability: '$response->{name}', '$response->{description}'", "APICHANGE" );
+
+ return $self->success( $response, "Capability was created." );
+ }
+ else {
+ return $self->alert( "Capability creation failed." );
+ }
+}
+
+sub update {
+ my $self = shift;
+ my $name = $self->param('name');
+ my $params = $self->req->json;
+
+ if ( !&is_oper($self) ) {
+ return $self->forbidden();
+ }
+
+ if ( !defined($params) ) {
+ return $self->alert("Parameters must be in JSON format.");
+ }
+
+ my $description = $params->{description} if defined($params->{description});
+
+ my $capability = $self->db->resultset('Capability')->find( { name => $name } );
+ if ( !defined($capability) or $capability eq "" ) {
+ return $self->not_found();
+ }
+
+ if ( !defined($description) or $description eq "" ) {
+ return $self->alert( "Description is required." );
+ }
+
+ my $values = {
+ description => $description
+ };
+
+ my $rs = $capability->update($values);
+ if ($rs) {
+ my $response;
+ $response->{name} = $rs->name;
+ $response->{description} = $rs->description;
+ $response->{lastUpdated} = $rs->last_updated;
+
+ &log( $self, "Updated Capability: '$response->{name}', '$response->{description}'", "APICHANGE" );
+
+ return $self->success( $response, "Capability was updated." );
+ }
+ else {
+ return $self->alert( "Capability update failed." );
+ }
+}
+
+sub delete {
+ my $self = shift;
+ my $name = $self->param('name');
+
+ if ( !&is_oper($self) ) {
+ return $self->forbidden();
+ }
+
+ my $capability = $self->db->resultset('Capability')->find( { name => $name } );
+ if ( !defined($capability) ) {
+ return $self->not_found();
+ }
+
+ # make sure no api_capability refers to this capability
+ my $rs_data = $self->db->resultset("ApiCapability")->find( {'me.capability' => $name} );
+ if (defined($rs_data)) {
+ my $reference_id = $rs_data->id;
+ return $self->alert( "Capability \'$name\' is refered by an api_capability mapping: $reference_id. Deletion failed." );
+ }
+
+ my $rs = $capability->delete();
+ if ($rs) {
+ return $self->success_message("Capability deleted.");
+ } else {
+ return $self->alert( "Capability deletion failed." );
+ }
+}
+
+1;
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/9546e8ad/traffic_ops/app/lib/TrafficOpsRoutes.pm
----------------------------------------------------------------------
diff --git a/traffic_ops/app/lib/TrafficOpsRoutes.pm b/traffic_ops/app/lib/TrafficOpsRoutes.pm
index ab6e5a7..e808b29 100644
--- a/traffic_ops/app/lib/TrafficOpsRoutes.pm
+++ b/traffic_ops/app/lib/TrafficOpsRoutes.pm
@@ -681,6 +681,23 @@ sub api_routes {
# Supports ?orderby=key
$r->get("/api/$version/roles")->over( authenticated => 1 )->to( 'Role#index', namespace => $namespace );
+ # -- CAPABILITIES
+ # Supports ?orderby=key
+ $r->get("/api/$version/capabilities")->over( authenticated => 1 )->to( 'Capability#all', namespace => $namespace );
+ $r->get("/api/$version/capabilities/:name")->over( authenticated => 1 )->to( 'Capability#name', namespace => $namespace );
+ $r->put("/api/$version/capabilities/:name")->over( authenticated => 1 )->to( 'Capability#update', namespace => $namespace );
+ $r->post("/api/$version/capabilities")->over( authenticated => 1 )->to( 'Capability#create', namespace => $namespace );
+ $r->delete("/api/$version/capabilities/:name")->over( authenticated => 1 )->to( 'Capability#delete', namespace => $namespace );
+
+ # -- API-CAPABILITIES
+ # Supports ?orderby=key
+ $r->get("/api/$version/api_capabilities")->over( authenticated => 1 )->to( 'ApiCapability#all', namespace => $namespace );
+ $r->get("/api/$version/api_capabilities/:id")->over( authenticated => 1 )->to( 'ApiCapability#index', namespace => $namespace );
+ $r->get("/api/$version/api_capabilities/capability/:name")->over( authenticated => 1 )->to( 'ApiCapability#capName', namespace => $namespace );
+ $r->put("/api/$version/api_capabilities/:id")->over( authenticated => 1 )->to( 'ApiCapability#update', namespace => $namespace );
+ $r->post("/api/$version/api_capabilities")->over( authenticated => 1 )->to( 'ApiCapability#create', namespace => $namespace );
+ $r->delete("/api/$version/api_capabilities/:id")->over( authenticated => 1 )->to( 'ApiCapability#delete', namespace => $namespace );
+
# -- SERVERS
# -- SERVERS: CRUD
$r->get("/api/$version/servers")->over( authenticated => 1 )->to( 'Server#index', namespace => $namespace );