mirror of
https://github.com/Fishwaldo/huginn.git
synced 2025-03-16 03:41:41 +00:00
Merge pull request #939 from cantino/dry_run_with_event
Add support for sending an event in a "Dry Run"
This commit is contained in:
commit
67ff37a9f8
9 changed files with 150 additions and 28 deletions
|
@ -34,10 +34,67 @@ class @Utils
|
|||
body?(modal.querySelector('.modal-body'))
|
||||
$(modal).modal('show')
|
||||
|
||||
@handleDryRunButton: (button, data = $(button.form).serialize()) ->
|
||||
@handleDryRunButton: (button, data = if button.form then $(':input[name!="_method"]', button.form).serialize() else '') ->
|
||||
$(button).prop('disabled', true)
|
||||
cleanup = -> $(button).prop('disabled', false)
|
||||
|
||||
url = $(button).data('action-url')
|
||||
with_event_mode = $(button).data('with-event-mode')
|
||||
|
||||
if with_event_mode is 'no'
|
||||
return @invokeDryRun(url, data, cleanup)
|
||||
|
||||
Utils.showDynamicModal """
|
||||
<h5>Event to send#{if with_event_mode is 'maybe' then ' (Optional)' else ''}</h5>
|
||||
<form class="dry-run-form" method="post">
|
||||
<div class="form-group">
|
||||
<textarea rows="10" name="event" class="payload-editor" data-height="200">
|
||||
{}
|
||||
</textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input value="Dry Run" class="btn btn-primary" type="submit" />
|
||||
</div>
|
||||
</form>
|
||||
""",
|
||||
body: (body) =>
|
||||
form = $(body).find('.dry-run-form')
|
||||
payload_editor = form.find('.payload-editor')
|
||||
if previous = $(button).data('payload')
|
||||
payload_editor.text(previous)
|
||||
window.setupJsonEditor(payload_editor)
|
||||
form.submit (e) =>
|
||||
e.preventDefault()
|
||||
json = $(e.target).find('.payload-editor').val()
|
||||
json = '{}' if json == ''
|
||||
try
|
||||
payload = JSON.parse(json)
|
||||
throw true unless payload.constructor is Object
|
||||
if Object.keys(payload).length == 0
|
||||
json = ''
|
||||
else
|
||||
json = JSON.stringify(payload)
|
||||
catch
|
||||
alert 'Invalid JSON object.'
|
||||
return
|
||||
if json == ''
|
||||
if with_event_mode is 'yes'
|
||||
alert 'Event is required for this agent to run.'
|
||||
return
|
||||
dry_run_data = data
|
||||
$(button).data('payload', null)
|
||||
else
|
||||
dry_run_data = "event=#{encodeURIComponent(json)}&#{data}"
|
||||
$(button).data('payload', json)
|
||||
$(body).closest('[role=dialog]').on 'hidden.bs.modal', =>
|
||||
@invokeDryRun(url, dry_run_data, cleanup)
|
||||
.modal('hide')
|
||||
title: 'Dry Run'
|
||||
onHide: cleanup
|
||||
|
||||
@invokeDryRun: (url, data, callback) ->
|
||||
$('body').css(cursor: 'progress')
|
||||
$.ajax type: 'POST', url: $(button).data('action-url'), dataType: 'json', data: data
|
||||
$.ajax type: 'POST', url: url, dataType: 'json', data: data
|
||||
.always =>
|
||||
$('body').css(cursor: 'auto')
|
||||
.done (json) =>
|
||||
|
@ -55,7 +112,7 @@ class @Utils
|
|||
find('.agent-dry-run-events').text(json.events).end().
|
||||
find('.agent-dry-run-memory').text(json.memory)
|
||||
title: 'Dry Run Results',
|
||||
onHide: -> $(button).prop('disabled', false)
|
||||
onHide: callback
|
||||
.fail (xhr, status, error) ->
|
||||
alert('Error: ' + error)
|
||||
$(button).prop('disabled', false)
|
||||
callback()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module DryRunnable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def dry_run!
|
||||
def dry_run!(event = nil)
|
||||
@dry_run = true
|
||||
|
||||
log = StringIO.new
|
||||
|
@ -13,7 +13,12 @@ module DryRunnable
|
|||
begin
|
||||
raise "#{short_type} does not support dry-run" unless can_dry_run?
|
||||
readonly!
|
||||
check
|
||||
if event
|
||||
raise "This agent cannot receive an event!" unless can_receive_events?
|
||||
receive([event])
|
||||
else
|
||||
check
|
||||
end
|
||||
rescue => e
|
||||
error "Exception during dry-run. #{e.message}: #{e.backtrace.join("\n")}"
|
||||
end
|
||||
|
|
|
@ -37,7 +37,7 @@ class AgentsController < ApplicationController
|
|||
def dry_run
|
||||
attrs = params[:agent] || {}
|
||||
if agent = current_user.agents.find_by(id: params[:id])
|
||||
# PUT /agents/:id/dry_run
|
||||
# POST /agents/:id/dry_run
|
||||
if attrs.present?
|
||||
type = agent.type
|
||||
agent = Agent.build_for_type(type, current_user, attrs)
|
||||
|
@ -50,7 +50,13 @@ class AgentsController < ApplicationController
|
|||
agent.name ||= '(Untitled)'
|
||||
|
||||
if agent.valid?
|
||||
results = agent.dry_run!
|
||||
if event_payload = params[:event]
|
||||
dummy_agent = Agent.build_for_type('ManualEventAgent', current_user, name: 'Dry-Runner')
|
||||
dummy_agent.readonly!
|
||||
event = dummy_agent.events.build(user: current_user, payload: event_payload)
|
||||
end
|
||||
|
||||
results = agent.dry_run!(event)
|
||||
|
||||
render json: {
|
||||
log: results[:log],
|
||||
|
|
|
@ -37,4 +37,16 @@ module AgentHelper
|
|||
}.join(delimiter).html_safe
|
||||
end
|
||||
end
|
||||
|
||||
def agent_dry_run_with_event_mode(agent)
|
||||
case
|
||||
when agent.cannot_receive_events?
|
||||
'no'.freeze
|
||||
when agent.cannot_be_scheduled?
|
||||
# incoming event is the only trigger for the agent
|
||||
'yes'.freeze
|
||||
else
|
||||
'maybe'.freeze
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<% if agent.can_dry_run? %>
|
||||
<li>
|
||||
<%= link_to icon_tag('glyphicon-refresh') + ' Dry Run', '#', 'data-action-url' => dry_run_agent_path(agent), tabindex: "-1", onclick: "Utils.handleDryRunButton(this, '_method=PUT')" %>
|
||||
<%= link_to icon_tag('glyphicon-refresh') + ' Dry Run', '#', 'data-action-url' => dry_run_agent_path(agent), 'data-with-event-mode' => agent_dry_run_with_event_mode(agent), tabindex: "-1", onclick: "Utils.handleDryRunButton(this)" %>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
|
|
|
@ -25,6 +25,6 @@
|
|||
<div class="form-group">
|
||||
<%= submit_tag "Save", :class => "btn btn-primary" %>
|
||||
<% if agent.can_dry_run? %>
|
||||
<%= button_tag class: 'btn btn-default agent-dry-run-button', type: 'button', 'data-action-url' => agent.persisted? ? dry_run_agent_path(agent) : dry_run_agents_path do %><%= icon_tag('glyphicon-refresh') %> Dry Run<% end %>
|
||||
<%= button_tag class: 'btn btn-default agent-dry-run-button', type: 'button', 'data-action-url' => agent.persisted? ? dry_run_agent_path(agent) : dry_run_agents_path, 'data-with-event-mode' => agent_dry_run_with_event_mode(agent) do %><%= icon_tag('glyphicon-refresh') %> Dry Run<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@ Huginn::Application.routes.draw do
|
|||
resources :agents do
|
||||
member do
|
||||
post :run
|
||||
put :dry_run
|
||||
post :dry_run
|
||||
post :handle_details_post
|
||||
put :leave_scenario
|
||||
delete :remove_events
|
||||
|
|
|
@ -7,10 +7,22 @@ describe DryRunnable do
|
|||
can_dry_run!
|
||||
|
||||
def check
|
||||
perform
|
||||
end
|
||||
|
||||
def receive(events)
|
||||
events.each do |event|
|
||||
perform(event.payload['prefix'])
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def perform(prefix = nil)
|
||||
log "Logging"
|
||||
create_event payload: { 'test' => 'foo' }
|
||||
create_event payload: { 'test' => "#{prefix}foo" }
|
||||
error "Recording error"
|
||||
create_event payload: { 'test' => 'bar' }
|
||||
create_event payload: { 'test' => "#{prefix}bar" }
|
||||
self.memory = { 'last_status' => 'ok', 'dry_run' => dry_run? }
|
||||
save!
|
||||
end
|
||||
|
@ -46,21 +58,6 @@ describe DryRunnable do
|
|||
expect(messages).to eq(['Logging', 'Recording error'])
|
||||
end
|
||||
|
||||
it "traps logging, event emission and memory updating, with dry_run? returning true" do
|
||||
results = nil
|
||||
|
||||
expect {
|
||||
results = @agent.dry_run!
|
||||
@agent.reload
|
||||
}.not_to change {
|
||||
[@agent.memory, counts]
|
||||
}
|
||||
|
||||
expect(results[:log]).to match(/\AI, .+ INFO -- : Logging\nE, .+ ERROR -- : Recording error\n/)
|
||||
expect(results[:events]).to eq([{ 'test' => 'foo' }, { 'test' => 'bar' }])
|
||||
expect(results[:memory]).to eq({ 'last_status' => 'ok', 'dry_run' => true })
|
||||
end
|
||||
|
||||
it "does not perform dry-run if Agent does not support dry-run" do
|
||||
stub(@agent).can_dry_run? { false }
|
||||
|
||||
|
@ -77,4 +74,36 @@ describe DryRunnable do
|
|||
expect(results[:events]).to eq([])
|
||||
expect(results[:memory]).to eq({})
|
||||
end
|
||||
|
||||
describe "dry_run!" do
|
||||
it "traps any destructive operations during a run" do
|
||||
results = nil
|
||||
|
||||
expect {
|
||||
results = @agent.dry_run!
|
||||
@agent.reload
|
||||
}.not_to change {
|
||||
[@agent.memory, counts]
|
||||
}
|
||||
|
||||
expect(results[:log]).to match(/\AI, .+ INFO -- : Logging\nE, .+ ERROR -- : Recording error\n/)
|
||||
expect(results[:events]).to eq([{ 'test' => 'foo' }, { 'test' => 'bar' }])
|
||||
expect(results[:memory]).to eq({ 'last_status' => 'ok', 'dry_run' => true })
|
||||
end
|
||||
|
||||
it "traps any destructive operations during a run when an event is given" do
|
||||
results = nil
|
||||
|
||||
expect {
|
||||
results = @agent.dry_run!(Event.new(payload: { 'prefix' => 'super' }))
|
||||
@agent.reload
|
||||
}.not_to change {
|
||||
[@agent.memory, counts]
|
||||
}
|
||||
|
||||
expect(results[:log]).to match(/\AI, .+ INFO -- : Logging\nE, .+ ERROR -- : Recording error\n/)
|
||||
expect(results[:events]).to eq([{ 'test' => 'superfoo' }, { 'test' => 'superbar' }])
|
||||
expect(results[:memory]).to eq({ 'last_status' => 'ok', 'dry_run' => true })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -377,6 +377,19 @@ describe AgentsController do
|
|||
[users(:bob).agents.count, users(:bob).events.count, users(:bob).logs.count, agent.name, agent.updated_at]
|
||||
}
|
||||
end
|
||||
|
||||
it "accepts an event" do
|
||||
sign_in users(:bob)
|
||||
agent = agents(:bob_website_agent)
|
||||
url_from_event = "http://xkcd.com/?from_event=1".freeze
|
||||
expect {
|
||||
post :dry_run, id: agent, event: { url: url_from_event }
|
||||
}.not_to change {
|
||||
[users(:bob).agents.count, users(:bob).events.count, users(:bob).logs.count, agent.name, agent.updated_at]
|
||||
}
|
||||
json = JSON.parse(response.body)
|
||||
expect(json['log']).to match(/^I, .* : Fetching #{Regexp.quote(url_from_event)}$/)
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE memory" do
|
||||
|
|
Loading…
Add table
Reference in a new issue