diff --git a/lib/ansible/runner.rb b/lib/ansible/runner.rb index 69130ad8505..17487e4b127 100644 --- a/lib/ansible/runner.rb +++ b/lib/ansible/runner.rb @@ -196,6 +196,7 @@ def run_via_cli(hosts, credentials, env_vars, extra_vars, tags: nil, ansible_run validate_params!(env_vars, extra_vars, tags, ansible_runner_method, playbook_or_role_args) base_dir = Dir.mktmpdir("ansible-runner") + debug = verbosity.to_i >= 5 || env_vars["ANSIBLE_KEEP_REMOTE_FILES"] cred_command_line, cred_env_vars, cred_extra_vars = credentials_info(credentials, base_dir) @@ -221,7 +222,7 @@ def run_via_cli(hosts, credentials, env_vars, extra_vars, tags: nil, ansible_run AwesomeSpawn.run("ansible-runner", :env => env_vars_hash, :params => params) end - res = response(base_dir, ansible_runner_method, result) + res = response(base_dir, ansible_runner_method, result, debug) ensure # Clean up the tmp dir for the sync method, for async we will clean it up after the job is finished and we've # read the output, that will be written into this directory. @@ -235,13 +236,14 @@ def run_via_cli(hosts, credentials, env_vars, extra_vars, tags: nil, ansible_run # @param result [AwesomeSpawn::CommandResult] Result object of AwesomeSpawn.run # @return [Ansible::Runner::ResponseAsync, Ansible::Runner::Response] response or ResponseAsync based on the # ansible_runner_method - def response(base_dir, ansible_runner_method, result) + def response(base_dir, ansible_runner_method, result, debug) if async?(ansible_runner_method) - Ansible::Runner::ResponseAsync.new(:base_dir => base_dir) + Ansible::Runner::ResponseAsync.new(:base_dir => base_dir, :debug => debug) else Ansible::Runner::Response.new(:base_dir => base_dir, :stdout => result.output, - :stderr => result.error) + :stderr => result.error, + :debug => debug) end end diff --git a/lib/ansible/runner/response.rb b/lib/ansible/runner/response.rb index 30abf367b5c..1f0ec041be5 100644 --- a/lib/ansible/runner/response.rb +++ b/lib/ansible/runner/response.rb @@ -3,7 +3,7 @@ class Runner class Response include Vmdb::Logging - attr_reader :base_dir, :ident + attr_reader :base_dir, :debug, :ident # Response object designed for holding full response from ansible-runner # @@ -12,13 +12,15 @@ class Response # @param stdout [String] Stdout from ansible-runner run # @param stderr [String] Stderr from ansible-runner run # @param ident [String] ansible-runner ident parameter - def initialize(base_dir:, return_code: nil, stdout: nil, stderr: nil, ident: "result") + # @param debug [Boolean] whether or not to delete base_dir after run (for debugging) + def initialize(base_dir:, return_code: nil, stdout: nil, stderr: nil, ident: "result", debug: false) @base_dir = base_dir @ident = ident @return_code = return_code @stdout = stdout @parsed_stdout = parse_stdout(stdout) if stdout @stderr = stderr + @debug = debug end # @return [Integer] Return code of the ansible-runner run, 0 == ok, others mean failure @@ -42,6 +44,8 @@ def cleanup_filesystem! return_code stdout + return if debug + FileUtils.remove_entry(base_dir) end diff --git a/lib/ansible/runner/response_async.rb b/lib/ansible/runner/response_async.rb index 25de87adf9c..384fccfc19f 100644 --- a/lib/ansible/runner/response_async.rb +++ b/lib/ansible/runner/response_async.rb @@ -3,7 +3,7 @@ class Runner class ResponseAsync include Vmdb::Logging - attr_reader :base_dir, :ident + attr_reader :base_dir, :debug, :ident # Response object designed for holding full response from ansible-runner # @@ -12,9 +12,11 @@ class ResponseAsync # @param ident [String] An identifier that will be used when generating the artifacts directory and can be used to # uniquely identify a playbook run. We use unique base dir per run, so this identifier can be static for # most cases. - def initialize(base_dir:, ident: "result") + # @param debug [Boolean] whether or not to delete base_dir after run (for debugging) + def initialize(base_dir:, ident: "result", debug: false) @base_dir = base_dir @ident = ident + @debug = debug end # @return [Boolean] true if the ansible job is still running, false when it's finished @@ -33,7 +35,7 @@ def response return if running? return @response if @response - @response = Ansible::Runner::Response.new(:base_dir => base_dir, :ident => ident) + @response = Ansible::Runner::Response.new(:base_dir => base_dir, :ident => ident, :debug => debug) @response.cleanup_filesystem! @response @@ -45,6 +47,7 @@ def response def dump { :base_dir => base_dir, + :debug => debug, :ident => ident } end diff --git a/spec/lib/ansible/runner/response_spec.rb b/spec/lib/ansible/runner/response_spec.rb index 9c439f7b6dc..bf3957f7662 100644 --- a/spec/lib/ansible/runner/response_spec.rb +++ b/spec/lib/ansible/runner/response_spec.rb @@ -95,4 +95,32 @@ end end end + + describe "cleanup_filesystem!" do + before do + expect(subject).to receive(:return_code) + expect(subject).to receive(:stdout) + end + + # Required so top level `after` can call `.rm_rf` properly + after { allow(FileUtils).to receive(:remove_entry).and_call_original } + + context "without debug" do + it "calls FileUtils.remove_entry" do + expect(FileUtils).to receive(:remove_entry).with(base_dir) + + subject.cleanup_filesystem! + end + end + + context "with debug" do + subject { described_class.new(:base_dir => base_dir, :ident => ident, :debug => true) } + + it "does not call FileUtils.remove_entry" do + expect(FileUtils).to receive(:remove_entry).with(base_dir).never + + subject.cleanup_filesystem! + end + end + end end diff --git a/spec/lib/ansible/runner_spec.rb b/spec/lib/ansible/runner_spec.rb index 73e5af84879..a3288ad2b7f 100644 --- a/spec/lib/ansible/runner_spec.rb +++ b/spec/lib/ansible/runner_spec.rb @@ -73,7 +73,7 @@ described_class.run(env_vars, extra_vars, playbook, :tags => tags) end - it "calls run with the correct verbosity" do + it "calls run with the correct verbosity (and triggers debug mode)" do expect(AwesomeSpawn).to receive(:run) do |command, options| expect(command).to eq("ansible-runner") @@ -81,7 +81,8 @@ expect(args).to eq(:ident => "result", :playbook => "playbook", :project_dir => "/path/to/my", "-vvvvv" => nil) end.and_return(result) - described_class.run(env_vars, extra_vars, playbook, :verbosity => 6) + response = described_class.run(env_vars, extra_vars, playbook, :verbosity => 6) + expect(response.debug).to eq(true) end it "calls run with become options" do