diff --git a/Netdisco/lib/Netdisco/DB/Result/NodeIp.pm b/Netdisco/lib/Netdisco/DB/Result/NodeIp.pm index a3707889..ccfb65d8 100644 --- a/Netdisco/lib/Netdisco/DB/Result/NodeIp.pm +++ b/Netdisco/lib/Netdisco/DB/Result/NodeIp.pm @@ -68,8 +68,8 @@ __PACKAGE__->belongs_to( oui => 'Netdisco::DB::Result::Oui', "$args->{foreign_alias}.oui" => { '=' => \"substring(cast($args->{self_alias}.mac as varchar) for 8)" } }; - } - , { join_type => 'LEFT' } + }, + { join_type => 'LEFT' } ); __PACKAGE__->has_many( node_ips => 'Netdisco::DB::Result::NodeIp', @@ -87,24 +87,31 @@ my $search_attr = { }; sub ip_aliases { - my ($row, $cond) = @_; - my $rs = $row->node_ips({ip => { '!=' => $row->ip }}); + my ($row, $cond, $attrs) = @_; + $cond ||= {}; + $attrs ||= {}; + my $rs = $row->node_ips({ip => { '!=' => $row->ip }}); $rs = $rs->search_rs({}, {'+columns' => 'dns'}) if $rs->has_dns_col; - return $rs->search($cond, $search_attr); + return $rs + ->search_rs({}, $search_attr) + ->search($cond, $attrs); } sub node_sightings { - my ($row, $cond) = @_; + my ($row, $cond, $attrs) = @_; + $cond ||= {}; + $attrs ||= {}; return $row - ->nodes({}, $search_attr) - ->search($cond, { + ->nodes({}, { '+columns' => [qw/ device.dns /], join => 'device', - }); + }) + ->search_rs({}, $search_attr) + ->search($cond, $attrs); } # accessors for custom formatted columns diff --git a/Netdisco/lib/Netdisco/DB/ResultSet/DevicePort.pm b/Netdisco/lib/Netdisco/DB/ResultSet/DevicePort.pm index 0ad88d47..ec9992da 100644 --- a/Netdisco/lib/Netdisco/DB/ResultSet/DevicePort.pm +++ b/Netdisco/lib/Netdisco/DB/ResultSet/DevicePort.pm @@ -4,91 +4,213 @@ use base 'DBIx::Class::ResultSet'; use strict; use warnings FATAL => 'all'; -sub by_ip { - my ($set, $ip) = @_; - return $set unless $ip; +=head1 search_by_mac( \%cond, \%attrs? ) - return $set->search( - { - 'me.ip' => $ip, - }, - { + my $set = $rs->search_by_mac({mac => '00:11:22:33:44:55'}); + +Like C, this returns a C<$resultset> of matching rows from the +DevicePort table. + +=over 4 + +=item * + +The C parameter must be a hashref containing a key C with +the value to search for. + +=item * + +Results are ordered by the creation timestamp. + +=item * + +The additional column C provides a preformatted timestamp of +the C field. + +=back + +=cut + +sub search_by_mac { + my ($rs, $cond, $attrs) = @_; + + die "mac address required for search_by_mac\n" + if ref {} ne ref $cond or !exists $cond->{mac}; + + $cond->{'me.mac'} = delete $cond->{mac}; + $attrs ||= {}; + + return $rs + ->search_rs({}, { + order_by => {'-desc' => 'me.creation'}, + '+select' => [ + \"to_char(me.creation, 'YYYY-MM-DD HH24:MI')", + ], + '+as' => [qw/ creation_stamp /], + }) + ->search($cond, $attrs); +} + +=head1 search_by_ip( \%cond, \%attrs? ) + + my $set = $rs->search_by_ip({ip => '192.0.2.1'}); + +Like C, this returns a C<$resultset> of matching rows from the +DevicePort table. + +=over 4 + +=item * + +The C parameter must be a hashref containing a key C with the IPv4 +or IPv6 value to search for in plain string form. + +=item * + +The additional column C provides a preformatted timestamp of +the C field in the C table. + +=item * + +A JOIN is performed on the C table in order to retrieve data required +for the C calculation. + +=back + +=cut + +sub search_by_ip { + my ($rs, $cond, $attrs) = @_; + + die "ip address required for search_by_ip\n" + if ref {} ne ref $cond or !exists $cond->{ip}; + + $cond->{'me.ip'} = delete $cond->{ip}; + $attrs ||= {}; + + return $rs + ->search_rs({}, { '+select' => [ \"to_char(last_discover - (uptime - lastchange) / 100 * interval '1 second', 'YYYY-MM-DD HH24:MI:SS')", ], '+as' => [qw/ lastchange_stamp /], join => 'device', - } - ); + }) + ->search($cond, $attrs); } -sub by_mac { - my ($set, $mac) = @_; - return $set unless $mac; +=head1 search_by_name( \%cond, \%attrs? ) - return $set->search( - { - 'me.mac' => $mac, - }, - { - order_by => {'-desc' => 'me.creation'}, - '+select' => [ - \"to_char(me.creation, 'YYYY-MM-DD HH24:MI')", - ], - '+as' => [qw/ creation /], - join => 'device', - }, - ); -} + my $set = $rs->search_by_name({name => 'sniffer'}); -# confusingly the "name" field is set using IOS "descrption" -# command but should not be confused with the "descr" field -sub by_name { - my ($set, $name) = @_; - return $set unless $name; - $name = "\%$name\%" if $name !~ m/\%/; +Like C, this returns a C<$resultset> of matching rows from the +DevicePort table. - return $set->search( - { - 'me.name' => { '-ilike' => $name }, - }, - { +=over 4 + +=item * + +The C parameter must be a hashref containing a key C with the +value to search for. The value may optionally include SQL wildcard characters. + +=item * + +Results are ordered by the port's Device IP and Port fields. + +=back + +=cut + +sub search_by_name { + my ($rs, $cond, $attrs) = @_; + + die "name required for search_by_name\n" + if ref {} ne ref $cond or !exists $cond->{name}; + + $cond->{'me.name'} = { '-ilike' => delete $cond->{name} }; + $attrs ||= {}; + + return $rs + ->search_rs({}, { order_by => [qw/ me.ip me.port /], - join => 'device', - }, - ); + }) + ->search($cond, $attrs); } -# should match edge ports only -sub by_vlan { - my ($set, $vlan) = @_; - return $set unless $vlan and $vlan =~ m/^\d+$/; +=head1 search_by_vlan( \%cond, \%attrs? ) - return $set->search( - { - 'me.vlan' => $vlan, - }, - { + my $set = $rs->search_by_vlan({vlan => 123}); + +Like C, this returns a C<$resultset> of matching rows from the +DevicePort table. + +=over 4 + +=item * + +The C parameter must be a hashref containing a key C with the +value to search for. + +=item * + +Results are ordered by the port's Device IP and Port fields. + +=back + +=cut + +sub search_by_vlan { + my ($rs, $cond, $attrs) = @_; + + die "vlan number required for search_by_vlan\n" + if ref {} ne ref $cond or !exists $cond->{vlan}; + + $cond->{'me.vlan'} = delete $cond->{vlan}; + $attrs ||= {}; + + return $rs + ->search_rs({}, { order_by => [qw/ me.ip me.port /], - join => 'device', - }, - ); + }) + ->search($cond, $attrs); } -sub by_port { - my ($set, $port) = @_; - return $set unless $port; +=head1 search_by_port( \%cond, \%attrs? ) - return $set->search( - { - 'me.port' => $port, - }, - { - order_by => [qw/ me.ip me.port /], - join => 'device', - }, - ); + my $set = $rs->search_by_port({port => 'FastEthernet0/23'}); + +Like C, this returns a C<$resultset> of matching rows from the +DevicePort table. + +=over 4 + +=item * + +The C parameter must be a hashref containing a key C with the +value to search for. + +=item * + +Results are ordered by the port's Device IP. + +=back + +=cut + +sub search_by_port { + my ($rs, $cond, $attrs) = @_; + + die "port required for search_by_port\n" + if ref {} ne ref $cond or !exists $cond->{port}; + + $cond->{'me.port'} = delete $cond->{port}; + $attrs ||= {}; + + return $rs + ->search_rs({}, { + order_by => [qw/ me.ip /], + }) + ->search($cond, $attrs); } 1; - diff --git a/Netdisco/lib/Netdisco/DB/ResultSet/Node.pm b/Netdisco/lib/Netdisco/DB/ResultSet/Node.pm index 23e19b1a..be24b60a 100644 --- a/Netdisco/lib/Netdisco/DB/ResultSet/Node.pm +++ b/Netdisco/lib/Netdisco/DB/ResultSet/Node.pm @@ -48,19 +48,17 @@ sub search_by_mac { $attrs ||= {}; return $rs - ->search_rs($cond, %$attrs) - ->search({}, - { - order_by => {'-desc' => 'time_last'}, - '+columns' => [qw/ device.dns /], - '+select' => [ - \"to_char(time_first, 'YYYY-MM-DD HH24:MI')", - \"to_char(time_last, 'YYYY-MM-DD HH24:MI')", - ], - '+as' => [qw/ time_first_stamp time_last_stamp /], - join => 'device', - }, - ); + ->search_rs({}, { + order_by => {'-desc' => 'time_last'}, + '+columns' => [qw/ device.dns /], + '+select' => [ + \"to_char(time_first, 'YYYY-MM-DD HH24:MI')", + \"to_char(time_last, 'YYYY-MM-DD HH24:MI')", + ], + '+as' => [qw/ time_first_stamp time_last_stamp /], + join => 'device', + }) + ->search($cond, $attrs); } 1; diff --git a/Netdisco/lib/Netdisco/DB/ResultSet/NodeIp.pm b/Netdisco/lib/Netdisco/DB/ResultSet/NodeIp.pm index b9f9bfd4..7721a2f0 100644 --- a/Netdisco/lib/Netdisco/DB/ResultSet/NodeIp.pm +++ b/Netdisco/lib/Netdisco/DB/ResultSet/NodeIp.pm @@ -24,7 +24,7 @@ my $search_attr = { =head1 search_by_ip( \%cond, \%attrs? ) - my $set = $rs->search_by_ip({ip => '123.123.123.123', active => 1}); + my $set = $rs->search_by_ip({ip => '192.0.2.1', active => 1}); Like C, this returns a C<$resultset> of matching rows from the NodeIp table. @@ -77,8 +77,8 @@ sub search_by_ip { if $rs->has_dns_col; return $rs - ->search_rs($cond, %$attrs) - ->search({}, $search_attr); + ->search_rs({}, $search_attr) + ->search($cond, $attrs); } =head1 search_by_name( \%cond, \%attrs? ) @@ -132,9 +132,9 @@ sub search_by_dns { $attrs ||= {}; return $rs - ->search_rs($cond, %$attrs) ->search_rs({}, {'+columns' => 'dns'}) - ->search({}, $search_attr); + ->search_rs({}, $search_attr) + ->search($cond, $attrs); } =head1 search_by_mac( \%cond, \%attrs? ) @@ -181,8 +181,8 @@ sub search_by_mac { if $rs->has_dns_col; return $rs - ->search_rs($cond, %$attrs) - ->search({}, $search_attr); + ->search_rs({}, $search_attr) + ->search($cond, $attrs); } 1; diff --git a/Netdisco/lib/Netdisco/Web/Search.pm b/Netdisco/lib/Netdisco/Web/Search.pm index 3d774c51..1cf84e35 100644 --- a/Netdisco/lib/Netdisco/Web/Search.pm +++ b/Netdisco/lib/Netdisco/Web/Search.pm @@ -76,7 +76,7 @@ ajax '/ajax/content/search/node' => sub { ->search_by_mac({mac => $mac->as_IEEE, @active}); my $ports = schema('netdisco')->resultset('DevicePort') - ->by_mac($mac->as_IEEE); + ->search_by_mac({mac => $mac->as_IEEE}); return unless $sightings->count or $ips->count @@ -161,10 +161,10 @@ ajax '/ajax/content/search/port' => sub { my $set; if ($q =~ m/^\d+$/) { - $set = schema('netdisco')->resultset('DevicePort')->by_vlan($q); + $set = schema('netdisco')->resultset('DevicePort')->search_by_vlan({vlan => $q}); } else { - $set = schema('netdisco')->resultset('DevicePort')->by_name($q); + $set = schema('netdisco')->resultset('DevicePort')->search_by_name({name => $q}); } return unless $set->count; @@ -213,9 +213,8 @@ get '/search' => sub { })->count) { params->{'tab'} = 'device'; } - elsif ($s->resultset('DevicePort')->search({ - name => { '-ilike' => "\%$q\%" }, - })->count) { + elsif ($s->resultset('DevicePort') + ->search_by_name({name => "\%$q\%"})->count) { params->{'tab'} = 'port'; } }