package App::Netdisco::Worker::Plugin; use Dancer ':syntax'; use Dancer::Plugin; use Dancer::Factory::Hook; use Scope::Guard 'guard'; use aliased 'App::Netdisco::Worker::Status'; use App::Netdisco::Util::Permission qw/check_acl_no check_acl_only/; my $store = Dancer::Factory::Hook->instance(); foreach my $phase (qw/check early main user/) { $store->install_hooks("nd2_core_${phase}"); } register 'register_worker' => sub { my ($self, $first, $second) = plugin_args(@_); my $workerconf = (ref $first eq 'HASH' ? $first : {}); my $code = (ref $first eq 'CODE' ? $first : $second); return error "bad param to register_worker" unless ((ref sub {} eq ref $code) and (ref {} eq ref $workerconf)); $workerconf->{phase} ||= 'user'; my $worker = sub { my $job = shift or return Status->error('missing job param'); # worker might be vendor/platform specific if (ref $job->device) { my $no = (exists $workerconf->{no} ? $workerconf->{no} : undef); my $only = (exists $workerconf->{only} ? $workerconf->{only} : undef); my $defer = Status->defer('worker is not applicable to this device'); return $defer if $no and check_acl_no($job->device, $no); return $defer if $only and not check_acl_only($job->device, $only); } my @newuserconf = (); my @userconf = @{ setting('device_auth') || [] }; # reduce device_auth by driver foreach my $stanza (@userconf) { next if exists $stanza->{driver} and exists $workerconf->{driver} and (($stanza->{driver} || '') ne ($workerconf->{driver} || '')); push @newuserconf, $stanza; } # per-device action but no device creds available return Status->defer('skipped with no device creds') if ref $job->device and 0 == scalar @newuserconf; # back up and restore device_auth my $guard = guard { set(device_auth => \@userconf) }; set(device_auth => \@newuserconf); # run worker return $code->($job, $workerconf); }; # D::Factory::Hook::register_hook() does not work?! my $hook = 'nd2_core_'. $workerconf->{phase}; hook $hook => $worker; }; register_plugin; true; =head1 NAME App::Netdisco::Worker::Plugin - Netdisco Workers =head1 Introduction L's plugin system allows users to write I to gather information from network devices using different I and store results in the database. For example, transports might be SNMP, SSH, or HTTPS. Workers might be combining those transports with application protocols such as SNMP, NETCONF (OpenConfig with XML), RESTCONF (OpenConfig with JSON), eAPI, or even CLI scraping. The combination of transport and protocol is known as a I. Workers can be restricted to certain vendor platforms using familiar ACL syntax. They are also attached to specific phases in Netdisco's backend operation (discover, macsuck, etc). =head1 Application Configuration The C and C settings list in YAML format the set of Perl module names which are the plugins to be loaded. Any change should go into your local C configuration file. If you want to view the default settings, see the C file in the C distribution. =head1 How to Configure The C setting is empty, and used only if you want to add new plugins but not change the set enabled by default. If you do want to add to or remove from the default set, then create a version of C instead. Netdisco prepends "C" to any entry in the list. For example, "C" will load the C package. You can prepend module names with "C" as shorthand for the "Netdisco extension" namespace. For example, "C" will load the L module. If an entry in the list starts with a "C<+>" (plus) sign then Netdisco attemps to load the module as-is, without prepending anything to the name. This allows you to have App::Netdisco Worker plugins in other namespaces. Plugin modules can either ship with the App::Netdisco distribution itself, or be installed separately. Perl uses the standard C<@INC> path searching mechanism to load the plugin modules. See the C and C settings in order to modify C<@INC> for loading local plugins. As an example, if your plugin is called "App::NetdiscoX::Worker::Plugin::MyPluginName" then it could live at: ~netdisco/nd-site-local/lib/App/NetdiscoX/Worker/Plugin/MyPluginName.pm The order of the entries is significant, workers being executed in the order which they appear in C and C (although see L for caveats). =cut