Skip to content

Commit

Permalink
Update for async ansible::runner
Browse files Browse the repository at this point in the history
  • Loading branch information
agrare committed Jul 27, 2018
1 parent 9710fcd commit 367544f
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 14 deletions.
19 changes: 15 additions & 4 deletions app/models/manageiq/providers/ansible_operation_workflow.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ def pre_playbook
def run_playbook
env_vars, extra_vars, playbook_path = options.values_at(:env_vars, :extra_vars, :playbook_path)

uuid = Ansible::Runner.run_async(env_vars, extra_vars, playbook_path)
if uuid.nil?
response = Ansible::Runner.run_async(env_vars, extra_vars, playbook_path)
if response.nil?
queue_signal(:abort, "Failed to run ansible playbook", "error")
else
context[:ansible_runner_uuid] = uuid
context[:ansible_runner_response] = response.dump
context[:ansible_runner_started_on] = Time.now.utc

update_attributes!(:context => context)
Expand All @@ -33,13 +33,24 @@ def run_playbook
end

def poll_runner
if Ansible::Runner.running?(context[:ansible_runner_uuid])
response = Ansible::Runner::ResponseAsync.load(context[:ansible_runner_response])
if response.running?
if context[:ansible_runner_started_on] + options[:timeout] < Time.now.utc
# TODO find out if this is blocking and we need a new state for it
response.stop

queue_signal(:abort, "Playbook has been running longer than timeout", "error")
else
queue_signal(:poll_runner, :deliver_on => deliver_on)
end
else
result = response.response

context[:ansible_runner_return_code] = result.return_code
context[:ansible_runner_stdout] = result.parsed_stdout

set_status("Playbook failed", "error") if result.return_code != 0

queue_signal(:post_playbook)
end
end
Expand Down
29 changes: 19 additions & 10 deletions spec/models/manageiq/providers/ansible_operation_workflow_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,17 @@

context ".run_playbook" do
let(:state) { "pre_playbook" }
let(:response_async) { Ansible::Runner::ResponseAsync.new(:base_dir => "/path/to/results") }

it "ansible-runner succeeds" do
uuid = "b4146f49-aec1-4f8f-a9aa-94afc99d5d80"
expect(Ansible::Runner).to receive(:run_async).and_return(uuid)
response_async = Ansible::Runner::ResponseAsync.new(:base_dir => "/path/to/results")

expect(Ansible::Runner).to receive(:run_async).and_return(response_async)
expect(job).to receive(:queue_signal).with(:poll_runner)

job.signal(:run_playbook)

expect(job.context[:ansible_runner_uuid]).to eq(uuid)
expect(job.context[:ansible_runner_response]).to eq(response_async.dump)
end

it "ansible-runner fails" do
Expand All @@ -106,17 +108,22 @@
end

context ".poll_runner" do
let(:state) { "running" }
let(:uuid) { "b4146f49-aec1-4f8f-a9aa-94afc99d5d80" }
let(:state) { "running" }
let(:response_async) { Ansible::Runner::ResponseAsync.new(:base_dir => "/path/to/results") }

before do
job.context[:ansible_runner_uuid] = uuid
allow(Ansible::Runner::ResponseAsync).to receive(:new).and_return(response_async)

job.context[:ansible_runner_response] = response_async.dump
job.context[:ansible_runner_started_on] = Time.now.utc
job.save!
end

it "ansible-runner completed" do
expect(Ansible::Runner).to receive(:running?).with(uuid).and_return(false)
expect(response_async).to receive(:running?).and_return(false)

response = Ansible::Runner::Response.new(response_async.dump.merge(:return_code => 0))
expect(response_async).to receive(:response).and_return(response)
expect(job).to receive(:queue_signal).with(:post_playbook)

job.signal(:poll_runner)
Expand All @@ -125,7 +132,7 @@
it "ansible-runner still running" do
now = Time.now.utc
allow(Time).to receive(:now).and_return(now)
expect(Ansible::Runner).to receive(:running?).with(uuid).and_return(true)
expect(response_async).to receive(:running?).and_return(true)
expect(job).to receive(:queue_signal).with(:poll_runner, :deliver_on => now + 1.minute)

job.signal(:poll_runner)
Expand All @@ -135,7 +142,8 @@
time = job.context[:ansible_runner_started_on] + job.options[:timeout] + 5.minutes

Timecop.travel(time) do
expect(Ansible::Runner).to receive(:running?).with(uuid).and_return(true)
expect(response_async).to receive(:running?).and_return(true)
expect(response_async).to receive(:stop)
expect(job).to receive(:queue_signal).with(:abort, "Playbook has been running longer than timeout", "error")

job.signal(:poll_runner)
Expand All @@ -144,11 +152,12 @@

context ".deliver_on" do
let(:options) { [{"ENV" => "VAR"}, %w(arg1 arg2), "/path/to/playbook", :poll_interval => 5.minutes] }
#let(:response_async) { Ansible::Runner::ResponseAsync.new(:base_dir => "/path/to/results") }

it "uses the option to queue poll_runner" do
now = Time.now.utc
allow(Time).to receive(:now).and_return(now)
expect(Ansible::Runner).to receive(:running?).with(uuid).and_return(true)
expect(response_async).to receive(:running?).and_return(true)
expect(job).to receive(:queue_signal).with(:poll_runner, :deliver_on => now + 5.minutes)

job.signal(:poll_runner)
Expand Down

0 comments on commit 367544f

Please sign in to comment.