Skip to content

Commit

Permalink
Add debugging for Ansible::Runner
Browse files Browse the repository at this point in the history
Allows keeping the file system generated by the `Ansible::Runner` lib
(aka: `EmbeddedAnsible`) via two parameters:

- Setting `verbosity` to 5 (or greater)
- Setting `ANSIBLE_KEEP_REMOTE_FILES` as an ENV var to '1'

This will cause `cleanup_filesystem!` to no-op and allows keeping the
filesystem in place without requiring a code change and application
restart, and doesn't require new field on services.

Note: Greater than 5 for verbosity is invalid as far as Ansible is
concerned, but that is `.chomped(1,5)` in a different part of the code
base, so using "6" could be a way to say "I would like `-vvvvv` plus
extra debugging from `MIQ`".
  • Loading branch information
NickLaMuro committed Aug 12, 2021
1 parent 75f9f42 commit 44b7455
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 11 deletions.
10 changes: 6 additions & 4 deletions lib/ansible/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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.
Expand All @@ -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

Expand Down
8 changes: 6 additions & 2 deletions lib/ansible/runner/response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
#
Expand All @@ -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
Expand All @@ -42,6 +44,8 @@ def cleanup_filesystem!
return_code
stdout

return if debug

FileUtils.remove_entry(base_dir)
end

Expand Down
9 changes: 6 additions & 3 deletions lib/ansible/runner/response_async.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
#
Expand All @@ -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
Expand All @@ -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
Expand All @@ -45,6 +47,7 @@ def response
def dump
{
:base_dir => base_dir,
:debug => debug,
:ident => ident
}
end
Expand Down
28 changes: 28 additions & 0 deletions spec/lib/ansible/runner/response_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
5 changes: 3 additions & 2 deletions spec/lib/ansible/runner_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,16 @@
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")

_method, _dir, _json, args = options[:params]
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
Expand Down

0 comments on commit 44b7455

Please sign in to comment.