App-Netdisco

 view release on metacpan or  search on metacpan

lib/App/Netdisco/Worker/Plugin.pm  view on Meta::CPAN

package App::Netdisco::Worker::Plugin;

use Dancer ':syntax';
use Dancer::Plugin;

use App::Netdisco::Util::Permission qw/acl_matches acl_matches_only/;
use aliased 'App::Netdisco::Worker::Status';

use Term::ANSIColor qw(:constants :constants256);
use Scope::Guard 'guard';
use Storable 'dclone';

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));

  my $package = (caller)[0];
  ($workerconf->{package} = $package) =~ s/^App::Netdisco::Worker::Plugin:://;
  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->{title}     ||= '';
  $workerconf->{phase}     ||= 'user';
  $workerconf->{namespace} ||= '_base_';
  $workerconf->{priority}  ||= (exists $workerconf->{driver}
    ? (setting('driver_priority')->{$workerconf->{driver}} || 0) : 0);

  my $worker = sub {
    my $job = shift or die 'missing job param';
    # use DDP; p $workerconf;

    debug YELLOW, "\N{RIGHTWARDS BLACK ARROW} worker ", GREY10, $workerconf->{package},
      ($workerconf->{pyworklet} ? (' '. $workerconf->{pyworklet}) : ''),
      GREY10, ' p', MAGENTA, $workerconf->{priority},
      ($workerconf->{title} ? (GREY10, ' "', BRIGHT_BLUE, $workerconf->{title}, GREY10, '"') : ''),
      RESET;

    if ($job->is_cancelled) {
      return $job->add_status( Status->info('skip: job is cancelled') );
    }

    if ($job->is_offline
        and $workerconf->{phase} eq 'main'
        and $workerconf->{priority} > 0
        and $workerconf->{priority} < setting('driver_priority')->{'direct'}) {

      return $job->add_status( Status->info('skip: networked worker but job is running offline') );
    }

    # support part-actions via action::namespace
    if ($job->only_namespace and $workerconf->{phase} ne 'check') {
      # skip namespaces not the requested ::namespace
      if (not ($workerconf->{namespace} eq lc( $job->only_namespace )
        # apart from discover::properties which needs to run, so that's early
        # phase for unknown devices, but not ::hooks/early (if implemented)
        or (($job->only_namespace ne 'hooks') and ($workerconf->{phase} eq 'early')
             and ($job->device and not $job->device->in_storage)) )) {

        return;
      }
    }

    my @newuserconf = ();
    my @userconf = @{ dclone (setting('device_auth') || []) };

    # 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);

      return $job->add_status( Status->info('skip: acls restricted') )
        if ($no and acl_matches($job->device, $no))
           or ($only and not acl_matches_only($job->device, $only));



( run in 0.368 second using v1.01-cache-2.11-cpan-5511b514fd6 )