add priority and namespace to support fancy worker overrides
This commit is contained in:
@@ -5,9 +5,9 @@ use warnings;
|
|||||||
|
|
||||||
use Module::Load ();
|
use Module::Load ();
|
||||||
use Module::Find qw/findsubmod findallmod/;
|
use Module::Find qw/findsubmod findallmod/;
|
||||||
use Dancer ':syntax';
|
|
||||||
|
|
||||||
# load worker plugins for our action
|
use Dancer ':syntax';
|
||||||
|
use Dancer::Factory::Hook;
|
||||||
|
|
||||||
sub import {
|
sub import {
|
||||||
my ($class, $action) = @_;
|
my ($class, $action) = @_;
|
||||||
@@ -17,6 +17,7 @@ sub import {
|
|||||||
my @check_plugins = findsubmod 'App::Netdisco::Worker::Plugin';
|
my @check_plugins = findsubmod 'App::Netdisco::Worker::Plugin';
|
||||||
my @phase_plugins = map { findallmod $_ } @check_plugins;
|
my @phase_plugins = map { findallmod $_ } @check_plugins;
|
||||||
|
|
||||||
|
# load worker plugins for our action
|
||||||
foreach my $plugin (@user_plugins, @check_plugins, @phase_plugins) {
|
foreach my $plugin (@user_plugins, @check_plugins, @phase_plugins) {
|
||||||
$plugin =~ s/^X::/App::NetdiscoX::Worker::Plugin::/;
|
$plugin =~ s/^X::/App::NetdiscoX::Worker::Plugin::/;
|
||||||
next unless $plugin =~ m/::Plugin::${action}(?:::|$)/i;
|
next unless $plugin =~ m/::Plugin::${action}(?:::|$)/i;
|
||||||
@@ -24,6 +25,32 @@ sub import {
|
|||||||
debug "loading worker plugin $plugin";
|
debug "loading worker plugin $plugin";
|
||||||
Module::Load::load $plugin;
|
Module::Load::load $plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# now vars->{workers} is populated, we set the dispatch order
|
||||||
|
my $store = Dancer::Factory::Hook->instance();
|
||||||
|
# use DDP; p vars->{'workers'};
|
||||||
|
|
||||||
|
foreach my $phase (qw/check early main user/) {
|
||||||
|
$store->install_hooks("nd2_core_${phase}");
|
||||||
|
|
||||||
|
foreach my $namespace (sort keys %{ vars->{'workers'}->{$phase} }) {
|
||||||
|
hook "nd2_core_${phase}" => sub {
|
||||||
|
vars->{'last_worker_ok'} = false;
|
||||||
|
vars->{'last_worker_priority'} = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach my $priority (sort {$b <=> $a} keys %{ vars->{'workers'}->{$phase}->{$namespace} }) {
|
||||||
|
|
||||||
|
# D::Factory::Hook::register_hook() does not work?!
|
||||||
|
hook "nd2_core_${phase}" => $_
|
||||||
|
for @{ vars->{'workers'}->{$phase}->{$namespace}->{$priority} };
|
||||||
|
|
||||||
|
hook "nd2_core_${phase}" => sub {
|
||||||
|
vars->{'last_worker_priority'} = $priority;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
true;
|
true;
|
||||||
|
|||||||
@@ -2,17 +2,11 @@ package App::Netdisco::Worker::Plugin;
|
|||||||
|
|
||||||
use Dancer ':syntax';
|
use Dancer ':syntax';
|
||||||
use Dancer::Plugin;
|
use Dancer::Plugin;
|
||||||
use Dancer::Factory::Hook;
|
|
||||||
|
|
||||||
use Scope::Guard 'guard';
|
use Scope::Guard 'guard';
|
||||||
use aliased 'App::Netdisco::Worker::Status';
|
use aliased 'App::Netdisco::Worker::Status';
|
||||||
use App::Netdisco::Util::Permission qw/check_acl_no check_acl_only/;
|
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 {
|
register 'register_worker' => sub {
|
||||||
my ($self, $first, $second) = plugin_args(@_);
|
my ($self, $first, $second) = plugin_args(@_);
|
||||||
|
|
||||||
@@ -21,10 +15,28 @@ register 'register_worker' => sub {
|
|||||||
return error "bad param to register_worker"
|
return error "bad param to register_worker"
|
||||||
unless ((ref sub {} eq ref $code) and (ref {} eq ref $workerconf));
|
unless ((ref sub {} eq ref $code) and (ref {} eq ref $workerconf));
|
||||||
|
|
||||||
$workerconf->{phase} ||= 'user';
|
my $package = (caller)[0];
|
||||||
|
if ($package =~ m/Plugin::(\w+)(?:::(\w+))?/) {
|
||||||
|
$workerconf->{action} = lc($1);
|
||||||
|
$workerconf->{namespace} = lc($2) if $2;
|
||||||
|
}
|
||||||
|
return error "failed to parse action in '$package'"
|
||||||
|
unless $workerconf->{action};
|
||||||
|
|
||||||
|
$workerconf->{phase} ||= 'user';
|
||||||
|
$workerconf->{namespace} ||= '_base_';
|
||||||
|
$workerconf->{priority} ||= (exists $workerconf->{driver}
|
||||||
|
? setting('driver_priority')->{$workerconf->{driver}} : 0);
|
||||||
|
|
||||||
my $worker = sub {
|
my $worker = sub {
|
||||||
my $job = shift or return Status->error('missing job param');
|
my $job = shift or return Status->error('missing job param');
|
||||||
|
# use DDP; p $workerconf;
|
||||||
|
|
||||||
|
# once workers at a given priority level in a namespace are successful,
|
||||||
|
# we can skip workers at lower priorities (that is, other drivers)
|
||||||
|
return Status->noop('skipped worker after previous namespace success')
|
||||||
|
if vars->{'last_worker_ok'}
|
||||||
|
and $workerconf->{priority} < vars->{'last_worker_priority'};
|
||||||
|
|
||||||
# worker might be vendor/platform specific
|
# worker might be vendor/platform specific
|
||||||
if (ref $job->device) {
|
if (ref $job->device) {
|
||||||
@@ -39,11 +51,14 @@ register 'register_worker' => sub {
|
|||||||
my @newuserconf = ();
|
my @newuserconf = ();
|
||||||
my @userconf = @{ setting('device_auth') || [] };
|
my @userconf = @{ setting('device_auth') || [] };
|
||||||
|
|
||||||
# reduce device_auth by driver
|
# reduce device_auth by driver and action filters
|
||||||
foreach my $stanza (@userconf) {
|
foreach my $stanza (@userconf) {
|
||||||
next if exists $stanza->{driver} and exists $workerconf->{driver}
|
next if exists $stanza->{driver} and exists $workerconf->{driver}
|
||||||
and (($stanza->{driver} || '') ne ($workerconf->{driver} || ''));
|
and (($stanza->{driver} || '') ne ($workerconf->{driver} || ''));
|
||||||
|
|
||||||
|
next if exists $stanza->{action}
|
||||||
|
and not _find_matchaction($workerconf, lc($stanza->{action}));
|
||||||
|
|
||||||
push @newuserconf, $stanza;
|
push @newuserconf, $stanza;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,11 +74,25 @@ register 'register_worker' => sub {
|
|||||||
return $code->($job, $workerconf);
|
return $code->($job, $workerconf);
|
||||||
};
|
};
|
||||||
|
|
||||||
# D::Factory::Hook::register_hook() does not work?!
|
# store the built worker as Worker.pm will build the dispatch order later on
|
||||||
my $hook = 'nd2_core_'. $workerconf->{phase};
|
push @{ vars->{'workers'}
|
||||||
hook $hook => $worker;
|
->{$workerconf->{phase}}
|
||||||
|
->{$workerconf->{namespace}}
|
||||||
|
->{$workerconf->{priority}} }, $worker;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sub _find_matchaction {
|
||||||
|
my ($conf, $action) = @_;
|
||||||
|
return true if !defined $action;
|
||||||
|
$action = [$action] if ref [] ne ref $action;
|
||||||
|
|
||||||
|
foreach my $f (@$action) {
|
||||||
|
return true if
|
||||||
|
$f eq $conf->{action} or $f eq "$conf->{action}::$conf->{namespace}";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
register_plugin;
|
register_plugin;
|
||||||
true;
|
true;
|
||||||
|
|
||||||
|
|||||||
@@ -100,6 +100,12 @@ sub run_workers {
|
|||||||
catch {
|
catch {
|
||||||
debug "=> $_" if $_;
|
debug "=> $_" if $_;
|
||||||
$self->jobstat->error($_) if $phase eq 'check';
|
$self->jobstat->error($_) if $phase eq 'check';
|
||||||
|
}
|
||||||
|
# allow workers to know whether previous worker of a different driver
|
||||||
|
# but the same namespace was successful
|
||||||
|
finally {
|
||||||
|
vars->{'last_worker_ok'} = $self->jobstat->is_ok
|
||||||
|
if not vars->{'last_worker_ok'};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -256,6 +256,13 @@ job_prio:
|
|||||||
extra_worker_plugins: []
|
extra_worker_plugins: []
|
||||||
# - Discover::ConfigBackup::CLI
|
# - Discover::ConfigBackup::CLI
|
||||||
|
|
||||||
|
driver_priority:
|
||||||
|
restconf: 500
|
||||||
|
netconf: 400
|
||||||
|
eapi: 300
|
||||||
|
cli: 200
|
||||||
|
snmp: 100
|
||||||
|
|
||||||
# ---------------
|
# ---------------
|
||||||
# GraphViz Export
|
# GraphViz Export
|
||||||
# ---------------
|
# ---------------
|
||||||
|
|||||||
Reference in New Issue
Block a user