Order tenants list in reply in heirarchic order

Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/c9181f24
Tree: 
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/c9181f24
Diff: 
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/c9181f24

Branch: refs/heads/master
Commit: c9181f247714297d0e4f7bb0a9683a56fa97070c
Parents: a1bf58f
Author: nir-sopher <[email protected]>
Authored: Thu Jun 1 16:00:28 2017 +0300
Committer: Jeremy Mitchell <[email protected]>
Committed: Tue Jul 18 12:12:31 2017 -0600

----------------------------------------------------------------------
 traffic_ops/app/lib/API/Tenant.pm     | 22 ++++---
 traffic_ops/app/lib/UI/TenantUtils.pm | 97 ++++++++++++++++++++++++++++++
 traffic_ops/app/t/api/1.2/tenant.t    | 21 +++++--
 3 files changed, 128 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/c9181f24/traffic_ops/app/lib/API/Tenant.pm
----------------------------------------------------------------------
diff --git a/traffic_ops/app/lib/API/Tenant.pm 
b/traffic_ops/app/lib/API/Tenant.pm
index 3bcdd0f..79795a4 100644
--- a/traffic_ops/app/lib/API/Tenant.pm
+++ b/traffic_ops/app/lib/API/Tenant.pm
@@ -17,6 +17,7 @@ package API::Tenant;
 #
 
 use UI::Utils;
+use UI::TenantUtils;
 
 use Mojo::Base 'Mojolicious::Controller';
 use Data::Dumper;
@@ -26,30 +27,30 @@ use MojoPlugins::Response;
 my $finfo = __FILE__ . ":";
 
 sub getTenantName {
-       my $self                = shift;
+       my $self                = shift;
        my $tenant_id           = shift;
        return defined($tenant_id) ? $self->db->resultset('Tenant')->search( { 
id => $tenant_id } )->get_column('name')->single() : "n/a";
 }
 
 sub isRootTenant {
-       my $self        = shift;
+       my $self        = shift;
        my $tenant_id   = shift;
        return !defined($self->db->resultset('Tenant')->search( { id => 
$tenant_id } )->get_column('parent_id')->single());
 }
 
 sub index {
        my $self        = shift;
-       my @data = ();
-       my %idnames;
-       my $orderby = $self->param('orderby') || "name";
 
+       my %idnames;
        my $rs_data = $self->db->resultset("Tenant")->search();
        while ( my $row = $rs_data->next ) {
                $idnames{ $row->id } = $row->name;
        }
 
-       my $rs_data = $self->db->resultset("Tenant")->search( undef, {order_by 
=> 'me.' . $orderby } );
-       while ( my $row = $rs_data->next ) {
+       my @data = ();
+       my $tenantUtils = UI::TenantUtils->new($self);
+       my @tenants_list = $tenantUtils->get_hierarchic_tenants_list();
+       foreach my $row (@tenants_list) {
                push(
                        @data, {
                                "id"           => $row->id,
@@ -122,6 +123,8 @@ sub update {
        }       
 
        if ( !defined( $params->{parentId}) && !$self->isRootTenant($id) ) {
+               # Cannot turn a simple tenant to a root tenant.
+               # Practically there is no problem with doing so, but it is to 
risky to be done by mistake. 
                return $self->alert("Parent Id is required.");
        }
        
@@ -134,12 +137,12 @@ sub update {
        if ( !$params->{active} && $self->isRootTenant($id)) {
                return $self->alert("Root user cannot be in-active.");
        }
-       
 
        if ( !defined($params->{parentId}) && !isRootTenant($id) ) {
                return $self->alert("Only the \"root\" tenant can have no 
parent.");
        }
        
+       #operation      
        my $values = {
                name      => $params->{name},
                active    => $params->{active},
@@ -185,6 +188,8 @@ sub create {
                return $self->alert("Tenant name is required.");
        }
 
+       #not allowing to create additional root tenants.
+       #there is no real problem with that, but no real use also
        my $parent_id = $params->{parentId};
        if ( !defined($parent_id) ) {
                return $self->alert("Parent Id is required.");
@@ -248,6 +253,7 @@ sub delete {
        if ( !defined($tenant) ) {
                return $self->not_found();
        }       
+
        my $name = $self->db->resultset('Tenant')->search( { id => $id } 
)->get_column('name')->single();
        
        my $existing_child = $self->db->resultset('Tenant')->search( { 
parent_id => $id }, {order_by => 'me.name' } )->get_column('name')->first();

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/c9181f24/traffic_ops/app/lib/UI/TenantUtils.pm
----------------------------------------------------------------------
diff --git a/traffic_ops/app/lib/UI/TenantUtils.pm 
b/traffic_ops/app/lib/UI/TenantUtils.pm
new file mode 100644
index 0000000..253c588
--- /dev/null
+++ b/traffic_ops/app/lib/UI/TenantUtils.pm
@@ -0,0 +1,97 @@
+package UI::TenantUtils;
+#
+#
+# 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 NetAddr::IP;
+use Data::Dumper;
+use Switch;
+use UI::Utils;
+
+
+sub new {
+       my $class = shift;
+       my $self  = {
+               context => shift,
+               user_tenant_id => -1,           
+               tenants_dict => undef,
+               root_tenants => undef,
+       };
+       return bless $self, $class;
+}
+
+sub get_hierarchic_tenants_list {
+       my $self = shift;
+       my $tree_root = shift;  
+       
+       $self->_init_tenants_if_needed();
+
+       my @stack = ();
+       if (defined($tree_root)){
+               push (@stack, $tree_root);
+       }
+       else {
+               push (@stack, reverse(@{$self->{root_tenants}}));
+       }
+
+       my @result = ();
+       while (@stack) {
+               my $tenant_id = pop @stack;
+               push (@result, $self->{tenants_dict}->{$tenant_id}{row});
+               push (@stack, 
reverse(@{$self->{tenants_dict}->{$tenant_id}{children}}));
+       }
+               
+       return @result; 
+}
+
+##############################################################
+
+sub _init_tenants {
+       my $self = shift;
+       my $tenants_table = $self->{context}->db->resultset("Tenant")->search( 
undef, { order_by => "id" });
+       
+       my @ordered_by_id = ();
+       $self->{tenants_dict} = {};
+       while ( my $row = $tenants_table->next ) {
+               push (@ordered_by_id, $row->id);
+               $self->{tenants_dict}->{$row->id} = {
+                       row => $row,
+                       parent => $row->parent_id,
+                       children => (),
+               }
+       }
+       
+       $self->{root_tenants} = ();
+       foreach my $key (@ordered_by_id) {
+               my $value = $self->{tenants_dict}->{$key};
+               my $parent = $value->{parent};
+               if (!defined($parent))
+               {
+                       push @{ $self->{root_tenants} }, $key;
+               }
+               else{
+                       push @{ $self->{tenants_dict}->{$parent}{children} }, 
$key;
+               }
+       }
+}
+
+sub _init_tenants_if_needed {
+       my $self = shift;
+       if (!defined($self->{tenants_dict})) {
+               $self->_init_tenants();
+       }
+}
+
+1;

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/c9181f24/traffic_ops/app/t/api/1.2/tenant.t
----------------------------------------------------------------------
diff --git a/traffic_ops/app/t/api/1.2/tenant.t 
b/traffic_ops/app/t/api/1.2/tenant.t
index 986f919..5d671ba 100644
--- a/traffic_ops/app/t/api/1.2/tenant.t
+++ b/traffic_ops/app/t/api/1.2/tenant.t
@@ -35,7 +35,7 @@ my $t      = Test::Mojo->new('TrafficOps');
 Test::TestHelper->unload_core_data($schema);
 Test::TestHelper->load_core_data($schema);
 
-ok $t->post_ok( '/login', => form => { u => Test::TestHelper::ADMIN_USER, p => 
Test::TestHelper::ADMIN_USER_PASSWORD } )->status_is(302)
+ok $t->post_ok( '/login', => form => { u => Test::TestHelper::ADMIN_ROOT_USER, 
p => Test::TestHelper::ADMIN_ROOT_USER_PASSWORD } )->status_is(302)
        ->or( sub { diag $t->tx->res->content->asset->{content}; } ), 'Should 
login?';
 
 #verifying the basic cfg
@@ -63,7 +63,12 @@ ok $t->post_ok('/api/1.2/tenants' => {Accept => 
'application/json'} => json => {
 ok $t->post_ok('/api/1.2/tenants' => {Accept => 'application/json'} => json => 
{
         "name" => "tenantB" })->status_is(400);
 
+#now getting it excepted
+ok $t->post_ok('/api/1.2/tenants' => {Accept => 'application/json'} => json => 
{
+        "name" => "tenantB", "parentId" => $root_tenant_id })->status_is(200);
+
 my $tenantA_id = &get_tenant_id('tenantA');
+my $tenantB_id = &get_tenant_id('tenantB');
 #rename, and move to active
 ok $t->put_ok('/api/1.2/tenants/' . $tenantA_id  => {Accept => 
'application/json'} => json => {
                        "name" => "tenantA2", "active" => 1, "parentId" => 
$root_tenant_id 
@@ -140,17 +145,25 @@ ok $t->post_ok('/api/1.2/tenants' => {Accept => 
'application/json'} => json => {
        ->json_is( "/response/parentId" =>  $tenantA_id)
             , 'Does the tenant details return?';
 
+my $tenantD_id = &get_tenant_id('tenantD');
+my $tenantE_id = &get_tenant_id('tenantE');
+
+-#list tenants- verify heirachic order
+$t->get_ok("/api/1.2/tenants")->status_is(200)->json_is( "/response/0/id", 
$root_tenant_id )
+       ->json_is( "/response/1/id", $tenantA_id)
+       ->json_is( "/response/2/id", $tenantD_id)
+       ->json_is( "/response/3/id", $tenantE_id)
+       ->json_is( "/response/4/id", $tenantB_id)->or( sub { diag 
$t->tx->res->content->asset->{content}; } );;
+
 #cannot delete a tenant that have children
 ok $t->delete_ok('/api/1.2/tenants/' . $tenantA_id)->status_is(400)
        ->json_is( "/alerts/0/text" => "Tenant 'tenantA2' has children 
tenant(s): e.g 'tenantD'. Please update these tenants and retry." )
        ->or( sub { diag $t->tx->res->content->asset->{content}; } );
 
-my $tenantD_id = &get_tenant_id('tenantD');
-my $tenantE_id = &get_tenant_id('tenantE');
-
 ok $t->delete_ok('/api/1.2/tenants/' . $tenantE_id)->status_is(200)->or( sub { 
diag $t->tx->res->content->asset->{content}; } );
 ok $t->delete_ok('/api/1.2/tenants/' . $tenantD_id)->status_is(200)->or( sub { 
diag $t->tx->res->content->asset->{content}; } );
 ok $t->delete_ok('/api/1.2/tenants/' . $tenantA_id)->status_is(200)->or( sub { 
diag $t->tx->res->content->asset->{content}; } );
+ok $t->delete_ok('/api/1.2/tenants/' . $tenantB_id)->status_is(200)->or( sub { 
diag $t->tx->res->content->asset->{content}; } );
 
 #cannot delete a tenant that have a delivery-service
 ok $t->delete_ok('/api/1.2/tenants/' . 10**9)->status_is(400)

Reply via email to