From e214bf26f7237e2a1c5465b7eeb65ee04e4db18e Mon Sep 17 00:00:00 2001 From: Ladislav Smola Date: Tue, 10 Jul 2018 17:26:25 +0200 Subject: [PATCH 1/7] Use ansible-runner instead of ansible-playbook Use ansible-runner instead of ansible-playbook Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1599798 --- lib/ansible/runner.rb | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/ansible/runner.rb b/lib/ansible/runner.rb index 432df502f18..0ae8cf00072 100644 --- a/lib/ansible/runner.rb +++ b/lib/ansible/runner.rb @@ -24,13 +24,25 @@ def run_queue(env_vars, extra_vars, playbook_path, user_id, queue_opts) private def run_via_cli(env_vars, extra_vars, playbook_path) - result = AwesomeSpawn.run!(ansible_command, :env => env_vars, :params => [{:extra_vars => JSON.dump(extra_vars)}, playbook_path]) + prepare_tmp_structure + + result = AwesomeSpawn.run!(ansible_command, :env => env_vars, :params => [{:cmdline => "--extra-vars '#{JSON.dump(extra_vars)}'", :playbook => playbook_path}]) JSON.parse(result.output) end + def prepare_tmp_structure + base_dir = "/tmp/ansible-runner/" + mkdir(base_dir) + mkdir(base_dir + 'project') # without this, there is a silent fail of the ansible-runner command see https://github.com/ansible/ansible-runner/issues/88 + end + + def mkdir(base_dir) + Dir.mkdir(base_dir) unless Dir.exist?(base_dir) + end + def ansible_command # TODO add possibility to use custom path, e.g. from virtualenv - "ansible-playbook" + "ansible-runner run /tmp/ansible-runner --json" end end end From 7bc49ac68f52e3f5b3591b9f435c426e18e7444b Mon Sep 17 00:00:00 2001 From: Ladislav Smola Date: Wed, 11 Jul 2018 14:04:22 +0200 Subject: [PATCH 2/7] Use mktmpdir to clean up ansible-runner files after the run Use mktmpdir to clean up ansible-runner files after the run --- lib/ansible/runner.rb | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/lib/ansible/runner.rb b/lib/ansible/runner.rb index 0ae8cf00072..70faf7dfadd 100644 --- a/lib/ansible/runner.rb +++ b/lib/ansible/runner.rb @@ -24,25 +24,21 @@ def run_queue(env_vars, extra_vars, playbook_path, user_id, queue_opts) private def run_via_cli(env_vars, extra_vars, playbook_path) - prepare_tmp_structure + Dir.mktmpdir("ansible-runner") do |base_dir| + mkdir(base_dir + '/project') # without this, there is a silent fail of the ansible-runner command see https://github.com/ansible/ansible-runner/issues/88 - result = AwesomeSpawn.run!(ansible_command, :env => env_vars, :params => [{:cmdline => "--extra-vars '#{JSON.dump(extra_vars)}'", :playbook => playbook_path}]) - JSON.parse(result.output) - end - - def prepare_tmp_structure - base_dir = "/tmp/ansible-runner/" - mkdir(base_dir) - mkdir(base_dir + 'project') # without this, there is a silent fail of the ansible-runner command see https://github.com/ansible/ansible-runner/issues/88 + result = AwesomeSpawn.run!(ansible_command(base_dir), :env => env_vars, :params => [{:cmdline => "--extra-vars '#{JSON.dump(extra_vars)}'", :playbook => playbook_path}]) + JSON.parse(result.output) + end end def mkdir(base_dir) Dir.mkdir(base_dir) unless Dir.exist?(base_dir) end - def ansible_command + def ansible_command(base_dir) # TODO add possibility to use custom path, e.g. from virtualenv - "ansible-runner run /tmp/ansible-runner --json" + "ansible-runner run #{base_dir} --json" end end end From c883cc8f1b0b40d1b4b6af331a150ec6c7598e22 Mon Sep 17 00:00:00 2001 From: Ladislav Smola Date: Fri, 13 Jul 2018 12:55:07 +0200 Subject: [PATCH 3/7] Deal with output which is JSON per line Deal with output which is JSON per line and for now, deal with possible non json lines. --- lib/ansible/runner.rb | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/ansible/runner.rb b/lib/ansible/runner.rb index 70faf7dfadd..1507ac605f6 100644 --- a/lib/ansible/runner.rb +++ b/lib/ansible/runner.rb @@ -28,7 +28,21 @@ def run_via_cli(env_vars, extra_vars, playbook_path) mkdir(base_dir + '/project') # without this, there is a silent fail of the ansible-runner command see https://github.com/ansible/ansible-runner/issues/88 result = AwesomeSpawn.run!(ansible_command(base_dir), :env => env_vars, :params => [{:cmdline => "--extra-vars '#{JSON.dump(extra_vars)}'", :playbook => playbook_path}]) - JSON.parse(result.output) + + parsed_stdout = [] + + # output is JSON per new line + result.output.each_line do |line| + # TODO(lsmola) we can remove exception handling when this is fixed + # https://github.com/ansible/ansible-runner/issues/89#issuecomment-404236832 , so it fails early if there is + # a non json line + begin + parsed_stdout << JSON.parse(line) + rescue => e + _log.warn("Couldn't parse JSON from: #{e}") + end + end + parsed_stdout end end From 3afb7375fe81285e41b2386064e544cdb5768fcd Mon Sep 17 00:00:00 2001 From: Ladislav Smola Date: Tue, 17 Jul 2018 13:09:28 +0200 Subject: [PATCH 4/7] Add a result object so we can easily extend it in the future Add a result object so we can easily extend it in the future --- lib/ansible/runner.rb | 21 ++++++-------------- lib/ansible/runner/response.rb | 36 ++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 15 deletions(-) create mode 100644 lib/ansible/runner/response.rb diff --git a/lib/ansible/runner.rb b/lib/ansible/runner.rb index 1507ac605f6..2628d3f73f0 100644 --- a/lib/ansible/runner.rb +++ b/lib/ansible/runner.rb @@ -29,30 +29,21 @@ def run_via_cli(env_vars, extra_vars, playbook_path) result = AwesomeSpawn.run!(ansible_command(base_dir), :env => env_vars, :params => [{:cmdline => "--extra-vars '#{JSON.dump(extra_vars)}'", :playbook => playbook_path}]) - parsed_stdout = [] - - # output is JSON per new line - result.output.each_line do |line| - # TODO(lsmola) we can remove exception handling when this is fixed - # https://github.com/ansible/ansible-runner/issues/89#issuecomment-404236832 , so it fails early if there is - # a non json line - begin - parsed_stdout << JSON.parse(line) - rescue => e - _log.warn("Couldn't parse JSON from: #{e}") - end - end - parsed_stdout + return Ansible::Runner::Response.new(:return_code => return_code(base_dir), :stdout => result.output, :stderr => result.error) end end + def return_code(base_dir) + File.read(File.join(base_dir, "artifacts/result/rc")) + end + def mkdir(base_dir) Dir.mkdir(base_dir) unless Dir.exist?(base_dir) end def ansible_command(base_dir) # TODO add possibility to use custom path, e.g. from virtualenv - "ansible-runner run #{base_dir} --json" + "ansible-runner run #{base_dir} --json -i result" end end end diff --git a/lib/ansible/runner/response.rb b/lib/ansible/runner/response.rb new file mode 100644 index 00000000000..3323ae429b3 --- /dev/null +++ b/lib/ansible/runner/response.rb @@ -0,0 +1,36 @@ +module Ansible + class Runner + class Response + include Vmdb::Logging + + attr_reader :return_code, :stdout, :stderr, :parsed_stdout + + def initialize(return_code:, stdout:, stderr:) + @return_code = return_code + @stdout = stdout + @parsed_stdout = parse_stdout(stdout) + @stderr = stderr + end + + private + + def parse_stdout(stdout) + parsed_stdout = [] + + # output is JSON per new line + stdout.each_line do |line| + # TODO(lsmola) we can remove exception handling when this is fixed + # https://github.com/ansible/ansible-runner/issues/89#issuecomment-404236832 , so it fails early if there is + # a non json line + begin + parsed_stdout << JSON.parse(line) + rescue => e + _log.warn("Couldn't parse JSON from: #{e}") + end + end + + parsed_stdout + end + end + end +end From ce9af21ed0f5eb1eecc753a81b70cc2715cfa6bf Mon Sep 17 00:00:00 2001 From: Ladislav Smola Date: Tue, 17 Jul 2018 13:18:15 +0200 Subject: [PATCH 5/7] Simplify the mkdir --- lib/ansible/runner.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/ansible/runner.rb b/lib/ansible/runner.rb index 2628d3f73f0..939562971d0 100644 --- a/lib/ansible/runner.rb +++ b/lib/ansible/runner.rb @@ -25,7 +25,7 @@ def run_queue(env_vars, extra_vars, playbook_path, user_id, queue_opts) def run_via_cli(env_vars, extra_vars, playbook_path) Dir.mktmpdir("ansible-runner") do |base_dir| - mkdir(base_dir + '/project') # without this, there is a silent fail of the ansible-runner command see https://github.com/ansible/ansible-runner/issues/88 + Dir.mkdir(File.join(base_dir, 'project')) # without this, there is a silent fail of the ansible-runner command see https://github.com/ansible/ansible-runner/issues/88 result = AwesomeSpawn.run!(ansible_command(base_dir), :env => env_vars, :params => [{:cmdline => "--extra-vars '#{JSON.dump(extra_vars)}'", :playbook => playbook_path}]) @@ -37,10 +37,6 @@ def return_code(base_dir) File.read(File.join(base_dir, "artifacts/result/rc")) end - def mkdir(base_dir) - Dir.mkdir(base_dir) unless Dir.exist?(base_dir) - end - def ansible_command(base_dir) # TODO add possibility to use custom path, e.g. from virtualenv "ansible-runner run #{base_dir} --json -i result" From b07524382a89efa0eac789a45c084ae9efdc36ec Mon Sep 17 00:00:00 2001 From: Ladislav Smola Date: Tue, 17 Jul 2018 13:32:59 +0200 Subject: [PATCH 6/7] Return integer return code Return integer return code, with possibility that the rc file is missing. --- lib/ansible/runner.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/ansible/runner.rb b/lib/ansible/runner.rb index 939562971d0..f994afe1c9c 100644 --- a/lib/ansible/runner.rb +++ b/lib/ansible/runner.rb @@ -34,7 +34,10 @@ def run_via_cli(env_vars, extra_vars, playbook_path) end def return_code(base_dir) - File.read(File.join(base_dir, "artifacts/result/rc")) + File.read(File.join(base_dir, "artifacts/result/rc")).to_i + rescue + _log.warn("Couldn't find ansible-runner return code") + 1 end def ansible_command(base_dir) From 5e9738f4d4a4ff7b43a0c6fc1e58688a0e1d1c01 Mon Sep 17 00:00:00 2001 From: Ladislav Smola Date: Tue, 17 Jul 2018 14:26:44 +0200 Subject: [PATCH 7/7] Remove extra return and reformat Remove extra return and reformat --- lib/ansible/runner.rb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/ansible/runner.rb b/lib/ansible/runner.rb index f994afe1c9c..d2933ae1172 100644 --- a/lib/ansible/runner.rb +++ b/lib/ansible/runner.rb @@ -27,9 +27,14 @@ def run_via_cli(env_vars, extra_vars, playbook_path) Dir.mktmpdir("ansible-runner") do |base_dir| Dir.mkdir(File.join(base_dir, 'project')) # without this, there is a silent fail of the ansible-runner command see https://github.com/ansible/ansible-runner/issues/88 - result = AwesomeSpawn.run!(ansible_command(base_dir), :env => env_vars, :params => [{:cmdline => "--extra-vars '#{JSON.dump(extra_vars)}'", :playbook => playbook_path}]) - - return Ansible::Runner::Response.new(:return_code => return_code(base_dir), :stdout => result.output, :stderr => result.error) + result = AwesomeSpawn.run!(ansible_command(base_dir), + :env => env_vars, + :params => [{:cmdline => "--extra-vars '#{JSON.dump(extra_vars)}'", + :playbook => playbook_path}]) + + Ansible::Runner::Response.new(:return_code => return_code(base_dir), + :stdout => result.output, + :stderr => result.error) end end