class Api::V2::JobInvocationsController
def action_permission
def action_permission case params[:action] when 'output', 'raw_output', 'outputs', 'hosts' :view when 'cancel' :cancel when 'rerun' :create else super end end
def allowed_nested_id
def allowed_nested_id %w(job_invocation_id) end
def cancel
def cancel if @job_invocation.task.cancellable? result = @job_invocation.cancel(params.fetch('force', false)) render :json => { :cancelled => result, :id => @job_invocation.id } else render :json => { :message => _('The job could not be cancelled.') }, :status => :unprocessable_entity end end
def create
def create composer = JobInvocationComposer.from_api_params( job_invocation_params ) composer.trigger! @job_invocation = composer.job_invocation @hosts = @job_invocation.targeting.hosts process_response @job_invocation rescue JobInvocationComposer::JobTemplateNotFound, JobInvocationComposer::FeatureNotFound => e not_found(error: { message: e.message }) end
def delayed_task_output(task, default: nil)
def delayed_task_output(task, default: nil) { :complete => false, :refresh => true, :output => default, :delayed => true, :start_at => task.start_at } end
def find_host
def find_host @host = @nested_obj.targeting.hosts.authorized(:view_hosts, Host).find(params['host_id']) rescue ActiveRecord::RecordNotFound not_found({ :error => { :message => (_("Host with id '%{id}' was not found") % { :id => params['host_id'] }) } }) end
def host_output(job_invocation, host, default: nil, since: nil, raw: false)
def host_output(job_invocation, host, default: nil, since: nil, raw: false) refresh = !job_invocation.finished? if (task = job_invocation.sub_task_for_host(host)) refresh = task.pending? output = output_lines_since(task, since) output = output.map { |set| set['output'] }.join if raw end { :complete => !refresh, :refresh => refresh, :output => output || default } end
def hosts
def hosts set_hosts_and_template_invocations set_statuses_and_smart_proxies @total = @job_invocation.targeting.hosts.size @hosts = @hosts.search_for(params[:search], :order => params[:order]).paginate(:page => params[:page], :per_page => params[:per_page]) @subtotal = @hosts.respond_to?(:total_entries) ? @hosts.total_entries : @hosts.sizes render :hosts, :layout => 'api/v2/layouts/index_layout' end
def index
def index @job_invocations = resource_scope_for_index end
def job_invocation_params
def job_invocation_params return @job_invocation_params if @job_invocation_params.present? job_invocation_params = params.fetch(:job_invocation, {}).dup if job_invocation_params[:feature].present? && job_invocation_params[:job_template_id].present? raise _("Only one of feature or job_template_id can be specified") end if job_invocation_params.key?(:ssh) job_invocation_params.merge!(job_invocation_params.delete(:ssh).permit(:effective_user, :effective_user_password)) end job_invocation_params[:inputs] ||= {} job_invocation_params[:inputs].permit! permit_provider_inputs job_invocation_params @job_invocation_params = job_invocation_params end
def output
def output if @nested_obj.task.scheduled? render :json => delayed_task_output(@nested_obj.task, :default => []) return end render :json => host_output(@nested_obj, @host, :default => [], :since => params[:since]) end
def output_lines_since(task, time)
def output_lines_since(task, time) since = time.to_f if time.present? line_sets = task.main_action.live_output line_sets = line_sets.drop_while { |o| o['timestamp'].to_f <= since } if since line_sets end
def outputs
def outputs hosts = @job_invocation.targeting.hosts.authorized(:view_hosts, Host) hosts = hosts.search_for(params['search_query']) if params['search_query'] raw = ActiveRecord::Type::Boolean.new.cast params['raw'] default_value = raw ? '' : [] outputs = hosts.map do |host| host_output(@job_invocation, host, :default => default_value, :since => params['since'], :raw => raw) .merge(host_id: host.id) end render :json => { :outputs => outputs } end
def parent_scope
def parent_scope resource_class.where(nil) end
def permit_provider_inputs(invocation_params)
def permit_provider_inputs(invocation_params) providers = RemoteExecutionProvider.providers.values.reject { |provider| !provider.respond_to?(:provider_input_namespace) || provider.provider_input_namespace.empty? } providers.each { |provider| invocation_params[provider.provider_input_namespace]&.permit! } end
def raw_output
def raw_output if @nested_obj.task.scheduled? render :json => delayed_task_output(@nested_obj.task) return end render :json => host_output(@nested_obj, @host, :raw => true) end
def rerun
def rerun composer = JobInvocationComposer.from_job_invocation(@job_invocation, params) if composer.rerun_possible? composer.trigger! @job_invocation = composer.job_invocation process_response @job_invocation else render :json => { :error => _('Could not rerun job %{id} because its template could not be found') % { :id => composer.reruns } }, :status => :not_found end end
def resource_name(resource = controller_name)
def resource_name(resource = controller_name) case resource when 'organization', 'location' nil else 'job_invocation' end end
def set_hosts_and_template_invocations
def set_hosts_and_template_invocations @pattern_template_invocations = @job_invocation.pattern_template_invocations.includes(:input_values) @hosts = @job_invocation.targeting.hosts.authorized(:view_hosts, Host) unless params[:search].nil? @hosts = @hosts.joins(:template_invocations) .where(:template_invocations => { :job_invocation_id => @job_invocation.id}) end @template_invocations = @job_invocation.template_invocations .where(host: @hosts) .includes(:input_values) end
def set_statuses_and_smart_proxies
def set_statuses_and_smart_proxies template_invocations = @template_invocations.includes(:run_host_job_task).to_a hosts = @hosts.to_a @host_statuses = Hash[hosts.map do |host| template_invocation = template_invocations.find { |ti| ti.host_id == host.id } task = template_invocation.try(:run_host_job_task) [host.id, template_invocation_status(task, @job_invocation.task)] end] @smart_proxy_id = Hash[template_invocations.map { |ti| [ti.host_id, ti.smart_proxy_id] }] @smart_proxy_name = Hash[template_invocations.map { |ti| [ti.host_id, ti.smart_proxy_name] }] end
def show
def show set_hosts_and_template_invocations @job_organization = Taxonomy.find_by(id: @job_invocation.task.input[:current_organization_id]) @job_location = Taxonomy.find_by(id: @job_invocation.task.input[:current_location_id]) if params[:host_status] == 'true' set_statuses_and_smart_proxies end end