App-Netdisco
view release on metacpan or search on metacpan
xt/208-vrf-default-leak-exclusion.t view on Meta::CPAN
#!/usr/bin/env perl
use strict; use warnings;
BEGIN { $ENV{DANCER_ENVDIR} = '/dev/null'; }
use Test::More 0.88;
use Test::File::ShareDir::Dist { 'App-Netdisco' => 'share/' };
use App::Netdisco;
use App::Netdisco::DB;
use App::Netdisco::Util::VRF 'each_vrf_instance';
use Dancer qw/:script !pass/;
# On Juniper the default instance's SNMP read also returns every virtual
# router's rows, so with store_vrfs on it was never whole and the default
# table never updated or retired. SNMP::Info 3.985001 names the instances
# mixed in (vrf_read_leaked) and drops their ports from the default readers
# once told them (vrf_exclude_ports), so each_vrf_instance reads the default
# instance a second time with those ports excluded.
config->{'enable_incomplete_walk_protection'} = 1;
package FakeSession;
sub new { my ($class, $snmp) = @_; return bless { snmp => $snmp }, $class }
sub get {
my ($self) = @_;
my $snmp = $self->{snmp};
if (($snmp->{answers}{ $snmp->{context} } || '') eq 'timeout') {
@$self{qw/ErrorStr ErrorNum/} = ('Timeout', -24);
return undef;
}
@$self{qw/ErrorStr ErrorNum/} = ('', 0);
return 12345;
}
# Context switching, walk records and error() as in xt/205. Has neither
# vrf_read_leaked nor vrf_exclude_ports, as SNMP::Info before 3.985001.
package FakeSNMP;
sub new {
my ($class, %vals) = @_;
my $self = bless { context => '', walk_failures => [], updates => 0, excluded => {},
exclusions => [], complete => {}, %vals }, $class;
$self->{session} = FakeSession->new($self);
return $self;
}
sub snmp_ver { 2 }
sub snmp_comm { 'public' }
sub class { 'SNMP::Info::Layer3::Fake' }
sub session { $_[0]{session} }
sub walk_failures { $_[0]{walk_failures} }
sub error { my $self = shift; my $error = $self->{error}; $self->{error} = undef; return $error }
sub update {
my ($self, %args) = @_;
my $target = ($args{Community} =~ m/\@(.+)$/ ? $1 : '');
# SNMP::Info::update() keeps the old session and returns false on failure
return if $self->{fail_update_to}{$target};
$self->{context} = $target;
$self->{updates}++;
# update() calls clear_cache(), which forgets recorded exclusions
$self->{excluded} = {};
return $self->{session};
}
sub vrf_read_complete {
my ($self, $name) = @_;
return ($self->{complete}{$name} // 1) unless $name eq 'default';
return 1 unless $self->{leaks};
return (grep { not $self->{excluded}{$_} } @{ $self->{leaks} }) ? 0 : 1;
}
sub i_vrf {
my $self = shift;
my $context = $self->{context};
push @{ $self->{walk_failures} }, { method => 'i_vrf', complete => 0, reason => 'timeout' }
if $self->{short_i_vrf}{$context};
return $self->{i_vrf}{$context} || {};
}
package FakeLeakSNMP;
our @ISA = ('FakeSNMP');
sub vrf_read_leaked {
my ($self, $name) = @_;
return undef unless $name eq 'default' and $self->{leaks} and $self->{context} eq '';
return [ sort grep { not $self->{excluded}{$_} } @{ $self->{leaks} } ];
}
sub vrf_exclude_ports {
my ($self, $name, $ports) = @_;
push @{ $self->{exclusions} },
{ name => $name, ports => [@$ports], context => $self->{context}, updates => $self->{updates} };
if ($self->{refuse_exclusion}) { $self->{error} = 'refused'; return undef }
$self->{excluded}{$name} = 1;
return 1;
}
package main;
my $device = App::Netdisco::DB->resultset('Device')->new_result({ ip => '192.0.2.1' });
sub switched { my $name = shift;
return { name => $name, contexts => [{ kind => 'vrf', id => $name, v2c => "%s\@$name", v3 => $name }] } }
my %instances = (
default => { name => 'default', contexts => [{ kind => 'none' }] },
blue => switched('blue'),
red => switched('red'),
);
sub run_each {
my ($snmp, $instances) = @_;
my @read;
my $reads = each_vrf_instance($device, $snmp, ($instances || \%instances),
sub { my ($name) = @_; push @read, [$name, $snmp->{context}]; return "data of $name" });
return ($reads, \@read);
}
( run in 0.631 second using v1.01-cache-2.11-cpan-145b269f2f3 )