From 367544f5b35896e3e1724ba5db17039b2f9ae5eb Mon Sep 17 00:00:00 2001 From: Adam Grare Date: Fri, 27 Jul 2018 09:37:55 -0400 Subject: [PATCH] Update for async ansible::runner --- .../providers/ansible_operation_workflow.rb | 19 +++++++++--- .../ansible_operation_workflow_spec.rb | 29 ++++++++++++------- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/app/models/manageiq/providers/ansible_operation_workflow.rb b/app/models/manageiq/providers/ansible_operation_workflow.rb index eeb5d55e9135..67137fc29cf9 100644 --- a/app/models/manageiq/providers/ansible_operation_workflow.rb +++ b/app/models/manageiq/providers/ansible_operation_workflow.rb @@ -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) @@ -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 diff --git a/spec/models/manageiq/providers/ansible_operation_workflow_spec.rb b/spec/models/manageiq/providers/ansible_operation_workflow_spec.rb index fa1cce806f47..65556494d465 100644 --- a/spec/models/manageiq/providers/ansible_operation_workflow_spec.rb +++ b/spec/models/manageiq/providers/ansible_operation_workflow_spec.rb @@ -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 @@ -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) @@ -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) @@ -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) @@ -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)