The Perl and Raku Conference 2025: Greenville, South Carolina - June 27-29 Learn more

use strict;
use Dancer ':syntax';
register_admin_task(
{ tag => 'orphaned',
label => 'Orphaned Devices / Networks',
provides_csv => 1,
}
);
get '/ajax/content/admin/orphaned' => require_role admin => sub {
my @tree = schema('netdisco')->resultset('Virtual::UnDirEdgesAgg')
->search( undef, { prefetch => 'device' } )->hri->all;
my @orphans
= schema('netdisco')->resultset('Virtual::OrphanedDevices')->search()
->order_by('ip')->hri->all;
return unless ( scalar @tree || scalar @orphans );
my @ordered;
if ( scalar @tree ) {
my %tree = map { $_->{'left_ip'} => $_ } @tree;
my $current_graph = 0;
my %visited = ();
my @to_visit = ();
foreach my $node ( keys %tree ) {
next if exists $visited{$node};
$current_graph++;
@to_visit = ($node);
while (@to_visit) {
my $node_to_visit = shift @to_visit;
$visited{$node_to_visit} = $current_graph;
push @to_visit,
grep { !exists $visited{$_} }
@{ $tree{$node_to_visit}->{'links'} };
}
}
my @graphs = ();
foreach my $key ( keys %visited ) {
push @{ $graphs[ $visited{$key} - 1 ] }, $tree{$key}->{'device'};
}
@ordered = sort { scalar @{$b} <=> scalar @{$a} } @graphs;
}
return if ( scalar @ordered < 2 && !scalar @tree );
if ( request->is_ajax ) {
template 'ajax/admintask/orphaned.tt',
{
orphans => \@orphans,
graphs => \@ordered,
},
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/admintask/orphaned_csv.tt',
{
orphans => \@orphans,
graphs => \@ordered,
},
{ layout => undef };
}
};
1;