From dd468efdd591bb17886e9fc4219367fcf3665d16 Mon Sep 17 00:00:00 2001 From: Oliver Gorwits Date: Tue, 16 Aug 2022 18:12:35 +0100 Subject: [PATCH] #834 VLAN Mismatch report - add sysname, port comment, and vlan diff --- .../DB/Result/Virtual/PortVLANMismatch.pm | 20 +++++++++++++------ .../Web/Plugin/Report/PortVLANMismatch.pm | 17 ++++++++++++++++ share/views/ajax/report/portvlanmismatch.tt | 16 +++++++++------ 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/lib/App/Netdisco/DB/Result/Virtual/PortVLANMismatch.pm b/lib/App/Netdisco/DB/Result/Virtual/PortVLANMismatch.pm index 5e201cef..f5c54876 100644 --- a/lib/App/Netdisco/DB/Result/Virtual/PortVLANMismatch.pm +++ b/lib/App/Netdisco/DB/Result/Virtual/PortVLANMismatch.pm @@ -23,10 +23,14 @@ __PACKAGE__->result_source_instance->view_definition(<<'ENDSQL'); WHERE vlan::text NOT IN (?, ?, ?, ?) GROUP BY ip, port) SELECT CASE WHEN length(ld.dns) > 0 THEN ld.dns ELSE host(ld.ip) END AS left_device, + ld.name AS left_name, lp.port AS left_port, + lp.name AS left_portname, (SELECT vlist FROM all_vlans WHERE ip=lp.ip AND port=lp.port) AS left_vlans, CASE WHEN length(rd.dns) > 0 THEN rd.dns ELSE host(rd.ip) END AS right_device, + rd.name AS right_name, rp.port AS right_port, + rp.name AS right_portname, (SELECT vlist FROM all_vlans WHERE ip=rp.ip AND port=rp.port) AS right_vlans FROM device ld JOIN device_port lp USING (ip) @@ -40,13 +44,17 @@ __PACKAGE__->result_source_instance->view_definition(<<'ENDSQL'); ENDSQL __PACKAGE__->add_columns( - 'left_device' => { data_type => 'text' }, - 'left_port' => { data_type => 'text' }, - 'left_vlans' => { data_type => 'text' }, + 'left_device' => { data_type => 'text' }, + 'left_name' => { data_type => 'text' }, + 'left_port' => { data_type => 'text' }, + 'left_portname' => { data_type => 'text' }, + 'left_vlans' => { data_type => 'text' }, - 'right_device' => { data_type => 'text' }, - 'right_port' => { data_type => 'text' }, - 'right_vlans' => { data_type => 'text' }, + 'right_device' => { data_type => 'text' }, + 'right_name' => { data_type => 'text' }, + 'right_port' => { data_type => 'text' }, + 'right_portname' => { data_type => 'text' }, + 'right_vlans' => { data_type => 'text' }, ); 1; diff --git a/lib/App/Netdisco/Web/Plugin/Report/PortVLANMismatch.pm b/lib/App/Netdisco/Web/Plugin/Report/PortVLANMismatch.pm index 147ae640..3f11371b 100644 --- a/lib/App/Netdisco/Web/Plugin/Report/PortVLANMismatch.pm +++ b/lib/App/Netdisco/Web/Plugin/Report/PortVLANMismatch.pm @@ -5,6 +5,7 @@ use Dancer::Plugin::DBIC; use Dancer::Plugin::Auth::Extensible; use App::Netdisco::Web::Plugin; +use List::MoreUtils qw/listcmp sort_by/; register_report( { category => 'Port', @@ -24,6 +25,22 @@ get '/ajax/content/report/portvlanmismatch' => require_login sub { }) ->hri->all; + # note that the generated list is rendered without HTML escape, + # so we MUST sanitise here with the grep + foreach my $res (@results) { + my @left = grep {m/^(?:n:)?\d+$/} map {s/\s//g; $_} split ',', $res->{left_vlans}; + my @right = grep {m/^(?:n:)?\d+$/} map {s/\s//g; $_} split ',', $res->{right_vlans}; + + my %new = (0 => [], 1 => []); + my %cmp = listcmp @left, @right; + foreach my $vlan (keys %cmp) { + map { push @{ $new{$_} }, ( (2 == scalar @{ $cmp{$vlan} }) ? $vlan : "$vlan" ) } @{ $cmp{$vlan} }; + } + + $res->{left_vlans} = join ', ', sort_by { (my $a = $_) =~ s/\D//g; sprintf "%04d", $a } @{ $new{0} }; + $res->{right_vlans} = join ', ', sort_by { (my $a = $_) =~ s/\D//g; sprintf "%04d", $a } @{ $new{1} }; + } + if (request->is_ajax) { my $json = to_json (\@results); template 'ajax/report/portvlanmismatch.tt', { results => $json }, { layout => 'noop' }; diff --git a/share/views/ajax/report/portvlanmismatch.tt b/share/views/ajax/report/portvlanmismatch.tt index ddb5affa..7637040a 100644 --- a/share/views/ajax/report/portvlanmismatch.tt +++ b/share/views/ajax/report/portvlanmismatch.tt @@ -20,27 +20,31 @@ $(document).ready(function() { { "data": 'left_device', "render": function(data, type, row, meta) { - return '' + he.encode(data || '') + ''; } + return '' + he.encode(data || '') + '' + + '
' + he.encode(row.left_name || ''); } }, { "data": 'left_port', "type": 'portsort', "render": function(data, type, row, meta) { return type === 'display' ? - '' + he.encode(data || '') + '' : - he.encode(data || ''); } + '' + he.encode(data || '') + '' + + '
' + he.encode(row.left_portname || '') + : he.encode(data || ''); } }, { "data": 'left_vlans' }, { "data": 'right_device', "render": function(data, type, row, meta) { - return '' + he.encode(data || '') + ''; } + return '' + he.encode(data || '') + '' + + '
' + he.encode(row.right_name || ''); } }, { "data": 'right_port', "type": 'portsort', "render": function(data, type, row, meta) { return type === 'display' ? - '' + he.encode(data || '') + '' : - he.encode(data || ''); } + '' + he.encode(data || '') + '' + + '
' + he.encode(row.right_portname || '') + : he.encode(data || ''); } }, { "data": 'right_vlans' }