#1001 support for FQDN node search while domain_suffix is set; add fallback to IPv4 host lookup search

This commit is contained in:
Oliver Gorwits
2023-03-16 15:53:25 +00:00
parent 2b8a45ef08
commit 6586815fc6
2 changed files with 52 additions and 12 deletions

View File

@@ -122,8 +122,9 @@ to search for. The value may optionally include SQL wildcard characters.
=item * =item *
The C<cond> parameter may optionally have a C<suffix> parameter which is a If C<dns> is a plain string, then the C<cond> parameter may optionally have a
regular expression of domain names - one of which must match the results. C<suffix> parameter which is a regular expression of domain names - one of
which must match the results.
=item * =item *
@@ -150,14 +151,37 @@ sub search_by_dns {
die "dns field required for search_by_dns\n" die "dns field required for search_by_dns\n"
if ref {} ne ref $cond or !exists $cond->{dns}; if ref {} ne ref $cond or !exists $cond->{dns};
(my $suffix = (delete $cond->{suffix} || '')) my $dns_field = delete $cond->{dns};
(my $suffix = ($cond->{suffix} || ''))
=~ s|\Q(?^\E[-xismu]*|(?|g; =~ s|\Q(?^\E[-xismu]*|(?|g;
$cond->{dns} = [ -and => if (q{} eq ref $dns_field and exists $cond->{suffix}) {
{ '-ilike' => delete $cond->{dns} }, (my $stripped_dns_field = $dns_field) =~ s/\.\%$//;
{ '~*' => "***:$suffix" }, (my $fqdn_field = $stripped_dns_field) .= '%';
]; $stripped_dns_field =~ s/$cond->{suffix}$// if $cond->{suffix};
$stripped_dns_field .= '.%';
$cond->{dns} = [ -or =>
[ -and =>
{ '-ilike' => $stripped_dns_field },
{ '~*' => "***:$suffix" },
],
[ -and =>
{ '-ilike' => $dns_field },
{ '~*' => "***:$suffix" },
],
{ '-ilike' => $fqdn_field },
];
}
elsif (q{} ne ref $dns_field) {
$cond->{dns} = $dns_field;
}
else {
$cond->{dns} = { '-ilike' => $dns_field };
}
delete $cond->{suffix};
return $rs return $rs
->search_rs({}, $order_by_time_last_and_join_oui) ->search_rs({}, $order_by_time_last_and_join_oui)
->search($cond, $attrs); ->search($cond, $attrs);

View File

@@ -10,6 +10,7 @@ use NetAddr::MAC ();
use POSIX qw/strftime/; use POSIX qw/strftime/;
use App::Netdisco::Web::Plugin; use App::Netdisco::Web::Plugin;
use App::Netdisco::Util::DNS 'ipv4_from_hostname';
use App::Netdisco::Util::Web 'sql_match'; use App::Netdisco::Util::Web 'sql_match';
register_search_tab({ register_search_tab({
@@ -208,42 +209,57 @@ get '/ajax/content/search/node' => require_login sub {
} }
} }
my $have_rows = 0;
my $set = schema(vars->{'tenant'})->resultset('NodeNbt') my $set = schema(vars->{'tenant'})->resultset('NodeNbt')
->search_by_name({nbname => $likeval, @active, @times}); ->search_by_name({nbname => $likeval, @active, @times});
++$have_rows if $set->has_rows;
unless ( $set->has_rows ) { unless ( $have_rows ) {
if ($node =~ m{^(?:$RE{net}{IPv4}|$RE{net}{IPv6})(?:/\d+)?$}i if ($node =~ m{^(?:$RE{net}{IPv4}|$RE{net}{IPv6})(?:/\d+)?$}i
and my $ip = NetAddr::IP::Lite->new($node)) { and my $ip = NetAddr::IP::Lite->new($node)) {
# search_by_ip() will extract cidr notation if necessary # search_by_ip() will extract cidr notation if necessary
$set = schema(vars->{'tenant'})->resultset('NodeIp') $set = schema(vars->{'tenant'})->resultset('NodeIp')
->search_by_ip({ip => $ip, @active, @times}); ->search_by_ip({ip => $ip, @active, @times});
++$have_rows if $set->has_rows;
} }
else { else {
$set = schema(vars->{'tenant'})->resultset('NodeIp') $set = schema(vars->{'tenant'})->resultset('NodeIp')
->search_by_dns({ ->search_by_dns({
($using_wildcards ? (dns => $likeval) : ($using_wildcards ? (dns => $likeval) :
(dns => "${likeval}.\%", (dns => "${likeval}.\%", suffix => setting('domain_suffix'))),
suffix => setting('domain_suffix'))),
@active, @active,
@times, @times,
}); });
++$have_rows if $set->has_rows;
# try DNS lookup as fallback
if (not $using_wildcards and not $have_rows) {
my $resolved_ip = ipv4_from_hostname($node);
if ($resolved_ip) {
$set = schema(vars->{'tenant'})->resultset('NodeIp')
->search_by_ip({ip => $resolved_ip, @active, @times});
++$have_rows if $set->has_rows;
}
}
# if the user selects Vendor search opt, then # if the user selects Vendor search opt, then
# we'll try the OUI company name as a fallback # we'll try the OUI company name as a fallback
if (param('show_vendor') and not $set->has_rows) { if (param('show_vendor') and not $have_rows) {
$set = schema(vars->{'tenant'})->resultset('NodeIp') $set = schema(vars->{'tenant'})->resultset('NodeIp')
->with_times ->with_times
->search( ->search(
{'oui.company' => { -ilike => ''.sql_match($node)}, @times}, {'oui.company' => { -ilike => ''.sql_match($node)}, @times},
{'prefetch' => 'oui'}, {'prefetch' => 'oui'},
); );
++$have_rows if $set->has_rows;
} }
} }
} }
return unless $set and $set->has_rows; return unless $set and ($have_rows or $set->has_rows);
$set = $set->search_rs({}, { order_by => 'me.mac' }); $set = $set->search_rs({}, { order_by => 'me.mac' });
return template 'ajax/search/node_by_ip.tt', { return template 'ajax/search/node_by_ip.tt', {