App-Netdisco
view release on metacpan or search on metacpan
xt/193-arpnip-vrf-collection.t view on Meta::CPAN
#!/usr/bin/env perl
use strict; use warnings;
no warnings 'once'; # local *glob = sub {} overrides below are single-use by design
BEGIN { $ENV{DANCER_ENVDIR} = '/dev/null'; }
use Test::More 0.88;
use Test::File::ShareDir::Dist { 'App-Netdisco' => 'share/' };
use lib 'xt/lib';
use App::Netdisco;
use App::Netdisco::DB;
use App::Netdisco::Backend::Job;
use App::Netdisco::Transport::SNMP ();
use App::Netdisco::Worker::Plugin::Arpnip::Nodes ();
use Try::Tiny;
use Dancer qw/:moose :script !pass/;
# The SNMP arpnip worker with store_vrfs on, run through the Runner as xt/192
# runs discover: SNMP is faked and store_arp records the entries it is given.
# The fake answers a VRF's neighbors only in that VRF's context, so a read in
# the wrong context returns nothing, as SNMP::Info does.
my $CONFIG = config();
$CONFIG->{logger} = 'console';
$CONFIG->{log} = ($ENV{'DANCER_DEBUG'} ? 'debug' : 'error');
Dancer::Logger->init('console', $CONFIG);
{
package MyWorker;
use Moo;
with 'App::Netdisco::Worker::Runner';
}
config->{'device_auth'} = [{driver => 'snmp'}];
config->{'enable_incomplete_walk_protection'} = 1;
config->{'dns'}->{'no'} = ['0.0.0.0/0'];
package FakeSNMP;
our $AUTOLOAD;
sub new {
my ($class, %vals) = @_;
return bless { walk_failures => [], context => '', contexts_asked => [], %vals }, $class;
}
sub walk_failures { $_[0]{walk_failures} }
sub walk_status { undef }
sub snmp_ver { $_[0]{snmp_ver} || 2 }
sub snmp_comm { 'public' }
sub update {
my ($self, %args) = @_;
$self->{context} = exists $args{Context} ? $args{Context}
: ($args{Community} =~ m/\@(.+)$/ ? $1 : '');
push @{ $self->{contexts_asked} }, $self->{context};
return 1;
}
sub _context_of {
my ($self, $name) = @_;
my $ctx = $self->{instances}{$name}{contexts}[0];
return '' if not $ctx or ($ctx->{kind} || '') eq 'none';
return $ctx->{id};
}
sub _in_default { return $_[0]{context} eq '' }
sub vrf_instances {
my $self = shift;
$self->{reads}{vrf_instances}++;
return $self->_in_default ? $self->{instances} : undef;
}
sub vrf_instances_complete {
my $self = shift;
$self->{reads}{vrf_instances_complete}++;
push @{ $self->{list_complete_read_in} }, $self->{context};
return $self->_in_default ? $self->{instances_complete} : undef;
}
sub _vrf_answer {
my ($self, $what, $name) = @_;
push @{ $self->{vrf_reads}{$name} }, $what;
return undef unless $self->{context} eq $self->_context_of($name);
return $self->{vrf}{$name}{$what};
}
sub vrf_neighbors {
my ($self, $name) = @_;
# a cut-short walk records itself, as SNMP::Info's walk_failures does
push @{ $self->{walk_failures} }, $self->{fail_neighbors_in}{$name}
if $self->{fail_neighbors_in}{$name};
return $self->_vrf_answer('neighbors', $name);
}
sub vrf_read_complete { $_[0]->_vrf_answer('complete', $_[1]) }
sub AUTOLOAD {
my $self = shift;
(my $method = $AUTOLOAD) =~ s/.*:://;
return if $method eq 'DESTROY';
$self->{reads}{$method}++;
return $self->{$method};
}
package main;
my %device_cols = (
ip => '192.0.2.1', name => 'router1', layers => '00000100', snmp_ver => 2,
snmp_class => 'SNMP::Info::Layer3',
);
# today's tables: one IPv4 ARP entry and one IPv6 neighbor
my %base_snmp = (
class => 'SNMP::Info::Layer3',
at_paddr => { '1.192.0.2.10' => '00:11:22:33:44:01' },
( run in 1.542 second using v1.01-cache-2.11-cpan-145b269f2f3 )