* implementation of GET and DELETE for Job Queue API * implement POST jobs submission to queue via API * implement GET /queue/backends API endpoint to get backend names
		
			
				
	
	
		
			180 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			180 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| package App::Netdisco::Web::API::Queue;
 | |
| 
 | |
| use Dancer ':syntax';
 | |
| use Dancer::Plugin::DBIC;
 | |
| use Dancer::Plugin::Swagger;
 | |
| use Dancer::Plugin::Auth::Extensible;
 | |
| 
 | |
| use App::Netdisco::JobQueue 'jq_insert';
 | |
| use Try::Tiny;
 | |
| 
 | |
| swagger_path {
 | |
|   tags => ['Queue'],
 | |
|   path => (setting('api_base') || '').'/queue/backends',
 | |
|   description => 'Return list of currently active backend names (usually FQDN)',
 | |
|   responses => { default => {} },
 | |
| }, get '/api/v1/queue/backends' => require_role api_admin => sub {
 | |
|   # from 1d988bbf7 this always returns an entry
 | |
|   my @names = schema(vars->{'tenant'})->resultset('DeviceSkip')
 | |
|     ->get_distinct_col('backend');
 | |
| 
 | |
|   return to_json \@names;
 | |
| };
 | |
| 
 | |
| swagger_path {
 | |
|   tags => ['Queue'],
 | |
|   path => (setting('api_base') || '').'/queue/jobs',
 | |
|   description => 'Return jobs in the queue, optionally filtered by fields',
 | |
|   parameters  => [
 | |
|     limit => {
 | |
|       description => 'Maximum number of Jobs to return',
 | |
|       type => 'integer',
 | |
|       default => (setting('jobs_qdepth') || 50),
 | |
|     },
 | |
|     device => {
 | |
|       description => 'IP address field of the Job',
 | |
|     },
 | |
|     port => {
 | |
|       description => 'Port field of the Job',
 | |
|     },
 | |
|     action => {
 | |
|       description => 'Action field of the Job',
 | |
|     },
 | |
|     status => {
 | |
|       description => 'Status field of the Job',
 | |
|     },
 | |
|     username => {
 | |
|       description => 'Username of the Job submitter',
 | |
|     },
 | |
|     userip => {
 | |
|       description => 'IP address of the Job submitter',
 | |
|     },
 | |
|     backend => {
 | |
|       description => 'Backend instance assigned the Job',
 | |
|     },
 | |
|   ],
 | |
|   responses => { default => {} },
 | |
| }, get '/api/v1/queue/jobs' => require_role api_admin => sub {
 | |
|   my @set = schema(vars->{'tenant'})->resultset('Admin')->search({
 | |
|     ( param('device')   ? ( device   => param('device') )   : () ),
 | |
|     ( param('port')     ? ( port     => param('port') )     : () ),
 | |
|     ( param('action')   ? ( action   => param('action') )   : () ),
 | |
|     ( param('status')   ? ( status   => param('status') )   : () ),
 | |
|     ( param('username') ? ( username => param('username') ) : () ),
 | |
|     ( param('userip')   ? ( userip   => param('userip') )   : () ),
 | |
|     ( param('backend')  ? ( backend  => param('backend') )  : () ),
 | |
|     -or => [
 | |
|       { 'log' => undef },
 | |
|       { 'log' => { '-not_like' => 'duplicate of %' } },
 | |
|     ],
 | |
|   }, {
 | |
|     order_by => { -desc => [qw/entered device action/] },
 | |
|     rows     => (param('limit') || setting('jobs_qdepth') || 50),
 | |
|   })->with_times->hri->all;
 | |
| 
 | |
|   return to_json \@set;
 | |
| };
 | |
| 
 | |
| swagger_path {
 | |
|   tags => ['Queue'],
 | |
|   path => (setting('api_base') || '').'/queue/jobs',
 | |
|   description => 'Delete jobs and skiplist entries, optionally filtered by fields',
 | |
|   parameters  => [
 | |
|     device => {
 | |
|       description => 'IP address field of the Job',
 | |
|     },
 | |
|     port => {
 | |
|       description => 'Port field of the Job',
 | |
|     },
 | |
|     action => {
 | |
|       description => 'Action field of the Job',
 | |
|     },
 | |
|     status => {
 | |
|       description => 'Status field of the Job',
 | |
|     },
 | |
|     username => {
 | |
|       description => 'Username of the Job submitter',
 | |
|     },
 | |
|     userip => {
 | |
|       description => 'IP address of the Job submitter',
 | |
|     },
 | |
|     backend => {
 | |
|       description => 'Backend instance assigned the Job',
 | |
|     },
 | |
|   ],
 | |
|   responses => { default => {} },
 | |
| }, del '/api/v1/queue/jobs' => require_role api_admin => sub {
 | |
|   my $gone = schema(vars->{'tenant'})->resultset('Admin')->search({
 | |
|     ( param('device')   ? ( device   => param('device') )   : () ),
 | |
|     ( param('port')     ? ( port     => param('port') )     : () ),
 | |
|     ( param('action')   ? ( action   => param('action') )   : () ),
 | |
|     ( param('status')   ? ( status   => param('status') )   : () ),
 | |
|     ( param('username') ? ( username => param('username') ) : () ),
 | |
|     ( param('userip')   ? ( userip   => param('userip') )   : () ),
 | |
|     ( param('backend')  ? ( backend  => param('backend') )  : () ),
 | |
|   })->delete;
 | |
| 
 | |
|   schema(vars->{'tenant'})->resultset('DeviceSkip')->search({
 | |
|     ( param('device')  ? ( device    => param('device') )  : () ),
 | |
|     ( param('action')  ? ( actionset => { '&&' => \[ 'ARRAY[?]', param('action') ] } ) : () ),
 | |
|     ( param('backend') ? ( backend   => param('backend') ) : () ),
 | |
|   })->delete;
 | |
| 
 | |
|   return to_json { deleted => ($gone || 0)};
 | |
| };
 | |
| 
 | |
| swagger_path {
 | |
|   tags => ['Queue'],
 | |
|   path => (setting('api_base') || '').'/queue/jobs',
 | |
|   description => 'Submit jobs to the queue',
 | |
|   parameters  => [
 | |
|     jobs => {
 | |
|       description => 'List of job specifications (action, device?, port?, extra?).',
 | |
|       default => '[]',
 | |
|       schema => {
 | |
|         type => 'array',
 | |
|         items => {
 | |
|           type => 'object',
 | |
|           properties => {
 | |
|             action => {
 | |
|               type => 'string',
 | |
|               required => 1,
 | |
|             },
 | |
|             device => {
 | |
|               type => 'string',
 | |
|               required => 0,
 | |
|             },
 | |
|             port => {
 | |
|               type => 'string',
 | |
|               required => 0,
 | |
|             },
 | |
|             extra => {
 | |
|               type => 'string',
 | |
|               required => 0,
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       },
 | |
|       in => 'body',
 | |
|     },
 | |
|   ],
 | |
|   responses => { default => {} },
 | |
| }, post '/api/v1/queue/jobs' => require_role api_admin => sub {
 | |
|   my $data = request->body || '';
 | |
|   my $jobs = (length $data ? try { from_json($data) } : []);
 | |
| 
 | |
|   (ref [] eq ref $jobs) or send_error('Malformed body', 400);
 | |
| 
 | |
|   foreach my $job (@$jobs) {
 | |
|       ref {} eq ref $job or send_error('Malformed job', 400);
 | |
|       $job->{username} = session('logged_in_user');
 | |
|       $job->{userip}   = request->remote_address;
 | |
|   }
 | |
| 
 | |
|   my $happy = jq_insert($jobs);
 | |
| 
 | |
|   return to_json { success => $happy };
 | |
| };
 | |
| 
 | |
| true;
 |