Files
netdisco/lib/App/Netdisco/Worker/Runner.pm
2017-10-01 08:18:13 +01:00

101 lines
2.8 KiB
Perl
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package App::Netdisco::Worker::Runner;
use Dancer qw/:moose :syntax/;
use Dancer::Factory::Hook;
use aliased 'App::Netdisco::Worker::Status';
use App::Netdisco::Util::Permission qw/check_acl_no check_acl_only/;
use Try::Tiny;
use Moo::Role;
use Module::Load ();
use Scope::Guard 'guard';
use namespace::clean;
has 'job' => (
is => 'rw',
);
has 'jobstat' => (
is => 'rw',
default => sub { Status->error("check phase did not pass for this action") },
);
after 'run', 'run_workers' => sub {
my $self = shift;
$self->job->update_status($self->jobstat);
};
# mixin code to run workers loaded via plugins
sub run {
my ($self, $job) = @_;
die 'cannot reuse a worker' if $self->job;
die 'bad job to run()'
unless ref $job eq 'App::Netdisco::Backend::Job';
$self->job($job);
my $action = $job->action;
Module::Load::load 'App::Netdisco::Worker' => $action;
my @newuserconf = ();
my @userconf = @{ setting('device_auth') || [] };
# reduce device_auth by only/no
if (ref $job->device) {
foreach my $stanza (@userconf) {
my $no = (exists $stanza->{no} ? $stanza->{no} : undef);
my $only = (exists $stanza->{only} ? $stanza->{only} : undef);
next if $no and check_acl_no($job->device, $no);
next if $only and not check_acl_only($job->device, $only);
push @newuserconf, $stanza;
}
}
# per-device action but no device creds available
return $self->jobstat->defer('deferred job 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);
$self->run_workers('nd2_core_check');
return if $self->jobstat->not_ok;
$self->jobstat( Status->error("no worker succeeded during main phase") );
$self->run_workers("nd2_core_${_}") for qw/early main user/;
}
sub run_workers {
my $self = shift;
my $hook = shift or return $self->jobstat->error('missing hook param');
my $store = Dancer::Factory::Hook->instance();
(my $phase = $hook) =~ s/^nd2_core_//;
debug "running workers for hook: $hook";
foreach my $worker (@{ $store->get_hooks_for($hook) }) {
try {
# could die or return undef or a scalar or Status or another class
my $retval = $worker->($self->job);
# update (save) the status if we're in check or main phases
#  check because it's a gatekeeper, main because it's the retval
$self->jobstat($retval)
if ($phase =~ m/^(?:check|main)$/)
and ref $retval eq 'App::Netdisco::Worker::Status'
and $self->jobstat->not_ok;
}
# errors at most phases are ignored
catch { $self->jobstat->error($_) if $phase eq 'check' };
# any successful check is a GO!
last if $phase eq 'check' and $self->jobstat->is_ok;
}
}
true;