foreman_ansible_core 2.2.0 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: e195d6690093de003b7ddaf9b807ac0d79ad775a
4
- data.tar.gz: 4286d8f97ffca80c17be58c302fb2aeffbf1d02f
2
+ SHA256:
3
+ metadata.gz: a45baed63d6c808d9df4b3717e427b332e45af0b49a6f652e197e7f151e5c023
4
+ data.tar.gz: da8b32e8eb3c6177299fd1fc2789f0db173e29a833323277edf4f89da9eb83de
5
5
  SHA512:
6
- metadata.gz: b1555fd4cb45577b25aa1f6b6ff4ba0ac02d354fa3c74e33790dc63e3454de9d70c1a01b4cc929b1096437395dfbdbb519e82e22f333710da2a5b5cf0d12331b
7
- data.tar.gz: 23e7b36347e64370135f75e18165d424ba6ee7bc429335be4e83a1778e05d6fd17c38c2ba1f76e8a0515cd424b4cf644c0b7995b876aa3f4055e4ccb5bcaf53c
6
+ metadata.gz: 49118a48bf6ebb4ede1e03b6a9278aa1d507da498620db057d0fc108ae7aabf4851b1ed8ee4f515553d64a5473ed6463835cc27e08e0606220804197b867fefa
7
+ data.tar.gz: 932fb010a258d877b038daa7d0e97f599242c25282dd7d7e7ed74fa77de1050b5251fd6f0690e60746b2bd6f25406cff63ac476983a90dccb929390d2b87f453
@@ -15,15 +15,20 @@ module ForemanAnsibleCore
15
15
 
16
16
  if ForemanTasksCore.dynflow_present?
17
17
  require 'foreman_tasks_core/runner'
18
- require 'foreman_ansible_core/playbook_runner'
18
+ require 'foreman_ansible_core/runner/playbook'
19
+ require 'foreman_ansible_core/runner/ansible_runner'
19
20
  require 'foreman_ansible_core/actions'
20
21
  end
21
22
 
22
23
  require 'foreman_remote_execution_core/actions'
23
24
  require 'foreman_ansible_core/remote_execution_core/ansible_runner'
24
- require 'foreman_ansible_core/remote_execution_core/settings_override'
25
- ForemanRemoteExecutionCore::Actions::RunScript.send(
26
- :prepend,
27
- ForemanAnsibleCore::RemoteExecutionCore::SettingsOverride
28
- )
25
+ require 'foreman_ansible_core/task_launcher/playbook'
26
+ require 'foreman_ansible_core/task_launcher/ansible_runner'
27
+
28
+ if defined?(SmartProxyDynflowCore)
29
+ SmartProxyDynflowCore::TaskLauncherRegistry.register('ansible-runner',
30
+ ForemanAnsibleCore::TaskLauncher::AnsibleRunner)
31
+ SmartProxyDynflowCore::TaskLauncherRegistry.register('ansible-playbook',
32
+ ForemanAnsibleCore::TaskLauncher::Playbook)
33
+ end
29
34
  end
@@ -8,7 +8,7 @@ module ForemanAnsibleCore
8
8
  # to execute the playbook run
9
9
  class RunPlaybook < ForemanTasksCore::Runner::Action
10
10
  def initiate_runner
11
- ForemanAnsibleCore::PlaybookRunner.new(
11
+ ForemanAnsibleCore::Runner::Playbook.new(
12
12
  input[:inventory],
13
13
  input[:playbook],
14
14
  input[:options]
@@ -5,13 +5,15 @@ module ForemanAnsibleCore
5
5
  # Takes an inventory and runs it through REXCore CommandRunner
6
6
  class AnsibleRunner < ::ForemanTasksCore::Runner::CommandRunner
7
7
  DEFAULT_REFRESH_INTERVAL = 1
8
+ CONNECTION_PROMPT = 'Are you sure you want to continue connecting (yes/no)? '
8
9
 
9
- def initialize(options)
10
- super(options)
11
- @playbook_runner = ForemanAnsibleCore::PlaybookRunner.new(
10
+ def initialize(options, suspended_action:)
11
+ super(options, :suspended_action => suspended_action)
12
+ @playbook_runner = ForemanAnsibleCore::Runner::Playbook.new(
12
13
  options['ansible_inventory'],
13
14
  options['script'],
14
- options
15
+ options,
16
+ :suspended_action => suspended_action
15
17
  )
16
18
  end
17
19
 
@@ -39,6 +41,21 @@ module ForemanAnsibleCore
39
41
  @command_in = @playbook_runner.command_in
40
42
  @command_pid = @playbook_runner.command_pid
41
43
  super
44
+ kill if unknown_host_key_fingerprint?
45
+ end
46
+
47
+ def kill
48
+ publish_exit_status(1)
49
+ ::Process.kill('SIGTERM', @command_pid)
50
+ close
51
+ end
52
+
53
+ private
54
+
55
+ def unknown_host_key_fingerprint?
56
+ last_output = @continuous_output.raw_outputs.last
57
+ return if last_output.nil?
58
+ last_output['output']&.lines&.last == CONNECTION_PROMPT
42
59
  end
43
60
  end
44
61
  end
@@ -0,0 +1,160 @@
1
+ require 'shellwords'
2
+
3
+ module ForemanAnsibleCore
4
+ module Runner
5
+ class AnsibleRunner < ForemanTasksCore::Runner::Parent
6
+ include ForemanTasksCore::Runner::Command
7
+
8
+ def initialize(input, suspended_action:)
9
+ super input, :suspended_action => suspended_action
10
+ @inventory = rebuild_secrets(rebuild_inventory(input), input)
11
+ @playbook = input.values.first[:input][:action_input][:script]
12
+ @root = working_dir
13
+ end
14
+
15
+ def start
16
+ prepare_directory_structure
17
+ write_inventory
18
+ write_playbook
19
+ start_ansible_runner
20
+ end
21
+
22
+ def refresh
23
+ return unless super
24
+ @counter ||= 1
25
+ @uuid ||= File.basename(Dir["#{@root}/artifacts/*"].first)
26
+ job_event_dir = File.join(@root, 'artifacts', @uuid, 'job_events')
27
+ loop do
28
+ files = Dir["#{job_event_dir}/*.json"].map do |file|
29
+ num = File.basename(file)[/\A\d+/].to_i unless file.include?('partial')
30
+ [file, num]
31
+ end
32
+ files_with_nums = files.select { |(_, num)| num && num >= @counter }.sort_by(&:last)
33
+ break if files_with_nums.empty?
34
+ logger.debug("[foreman_ansible] - processing event files: #{files_with_nums.map(&:first).inspect}}")
35
+ files_with_nums.map(&:first).each { |event_file| handle_event_file(event_file) }
36
+ @counter = files_with_nums.last.last + 1
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def handle_event_file(event_file)
43
+ logger.debug("[foreman_ansible] - parsing event file #{event_file}")
44
+ begin
45
+ event = JSON.parse(File.read(event_file))
46
+ if (hostname = event.dig('event_data', 'host'))
47
+ handle_host_event(hostname, event)
48
+ else
49
+ handle_broadcast_data(event)
50
+ end
51
+ true
52
+ rescue JSON::ParserError => e
53
+ logger.error("[foreman_ansible] - Error parsing runner event at #{event_file}: #{e.class}: #{e.message}")
54
+ logger.debug(e.backtrace.join("\n"))
55
+ end
56
+ end
57
+
58
+ def handle_host_event(hostname, event)
59
+ log_event("for host: #{hostname.inspect}", event)
60
+ publish_data_for(hostname, event['stdout'] + "\n", 'stdout') if event['stdout']
61
+ case event['event']
62
+ when 'runner_on_ok'
63
+ publish_exit_status_for(hostname, 0) if @exit_statuses[hostname].nil?
64
+ when 'runner_on_unreachable'
65
+ publish_exit_status_for(hostname, 1)
66
+ when 'runner_on_failed'
67
+ publish_exit_status_for(hostname, 2) if event.dig('event_data', 'ignore_errors').nil?
68
+ end
69
+ end
70
+
71
+ def handle_broadcast_data(event)
72
+ log_event("broadcast", event)
73
+ if event['event'] == 'playbook_on_stats'
74
+ header, *rows = event['stdout'].strip.lines.map(&:chomp)
75
+ @outputs.keys.select { |key| key.is_a? String }.each do |host|
76
+ line = rows.find { |row| row =~ /#{host}/ }
77
+ publish_data_for(host, [header, line].join("\n"), 'stdout')
78
+ end
79
+ else
80
+ broadcast_data(event['stdout'] + "\n", 'stdout')
81
+ end
82
+ end
83
+
84
+ def write_inventory
85
+ path = File.join(@root, 'inventory', 'hosts')
86
+ data_path = File.join(@root, 'data')
87
+ inventory_script = <<~INVENTORY_SCRIPT
88
+ #!/bin/sh
89
+ cat #{::Shellwords.escape data_path}
90
+ INVENTORY_SCRIPT
91
+ File.write(path, inventory_script)
92
+ File.write(data_path, JSON.dump(@inventory))
93
+ File.chmod(0o0755, path)
94
+ end
95
+
96
+ def write_playbook
97
+ File.write(File.join(@root, 'project', 'playbook.yml'), @playbook)
98
+ end
99
+
100
+ def start_ansible_runner
101
+ command = ['ansible-runner', 'run', @root, '-p', 'playbook.yml']
102
+ initialize_command(*command)
103
+ logger.debug("[foreman_ansible] - Running command '#{command.join(' ')}'")
104
+ end
105
+
106
+ def prepare_directory_structure
107
+ inner = %w[inventory project].map { |part| File.join(@root, part) }
108
+ ([@root] + inner).each do |path|
109
+ FileUtils.mkdir_p path
110
+ end
111
+ end
112
+
113
+ def log_event(description, event)
114
+ # TODO: replace this ugly code with block variant once https://github.com/Dynflow/dynflow/pull/323
115
+ # arrives in production
116
+ logger.debug("[foreman_ansible] - handling event #{description}: #{JSON.pretty_generate(event)}") if logger.level <= ::Logger::DEBUG
117
+ end
118
+
119
+ # Each per-host task has inventory only for itself, we must
120
+ # collect all the partial inventories into one large inventory
121
+ # containing all the hosts.
122
+ def rebuild_inventory(input)
123
+ action_inputs = input.values.map { |hash| hash[:input][:action_input] }
124
+ hostnames = action_inputs.map { |hash| hash[:name] }
125
+ inventories = action_inputs.map { |hash| hash[:ansible_inventory] }
126
+ host_vars = inventories.map { |i| i['_meta']['hostvars'] }.reduce(&:merge)
127
+
128
+ { '_meta' => { 'hostvars' => host_vars },
129
+ 'all' => { 'hosts' => hostnames,
130
+ 'vars' => inventories.first['all']['vars'] } }
131
+ end
132
+
133
+ def working_dir
134
+ return @root if @root
135
+ dir = ForemanAnsibleCore.settings[:working_dir]
136
+ @tmp_working_dir = true
137
+ if dir.nil?
138
+ Dir.mktmpdir
139
+ else
140
+ Dir.mktmpdir(nil, File.expand_path(dir))
141
+ end
142
+ end
143
+
144
+ def rebuild_secrets(inventory, input)
145
+ input.each do |host, host_input|
146
+ secrets = host_input['input']['action_input']['secrets']
147
+ per_host = secrets['per-host'][host]
148
+
149
+ new_secrets = {
150
+ 'ansible_ssh_pass' => inventory['ssh_password'] || per_host['ansible_ssh_pass'],
151
+ 'ansible_sudo_pass' => inventory['sudo_password'] || per_host['ansible_sudo_pass']
152
+ }
153
+ inventory['_meta']['hostvars'][host].update(new_secrets)
154
+ end
155
+
156
+ inventory
157
+ end
158
+ end
159
+ end
160
+ end
@@ -34,7 +34,7 @@ module ForemanAnsibleCore
34
34
  end
35
35
 
36
36
  def json_inventory_script
37
- File.expand_path('../../bin/json_inventory.sh', File.dirname(__FILE__))
37
+ File.expand_path('../../../bin/json_inventory.sh', File.dirname(__FILE__))
38
38
  end
39
39
 
40
40
  def setup_verbosity
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'foreman_tasks_core/runner/command_runner'
4
+ require_relative 'command_creator'
5
+ require 'tmpdir'
6
+ require 'net/ssh'
7
+
8
+ module ForemanAnsibleCore
9
+ module Runner
10
+ # Implements ForemanTasksCore::Runner::Base interface for running
11
+ # Ansible playbooks, used by the Foreman Ansible plugin and Ansible proxy
12
+ class Playbook < ForemanTasksCore::Runner::CommandRunner
13
+ attr_reader :command_out, :command_in, :command_pid
14
+
15
+ def initialize(inventory, playbook, options = {}, suspended_action:)
16
+ super :suspended_action => suspended_action
17
+ @inventory = rebuild_secrets(inventory, options[:secrets])
18
+ unknown_hosts.each do |host|
19
+ add_to_known_hosts(host)
20
+ end
21
+ @playbook = playbook
22
+ @options = options
23
+ initialize_dirs
24
+ end
25
+
26
+ def start
27
+ write_inventory
28
+ write_playbook
29
+ command = CommandCreator.new(inventory_file,
30
+ playbook_file,
31
+ @options).command
32
+ logger.debug('[foreman_ansible] - Initializing Ansible Runner')
33
+ Dir.chdir(@ansible_dir) do
34
+ initialize_command(*command)
35
+ logger.debug("[foreman_ansible] - Running command '#{command.join(' ')}'")
36
+ end
37
+ end
38
+
39
+ def kill
40
+ publish_data('== TASK ABORTED BY USER ==', 'stdout')
41
+ publish_exit_status(1)
42
+ ::Process.kill('SIGTERM', @command_pid)
43
+ close
44
+ end
45
+
46
+ def close
47
+ super
48
+ FileUtils.remove_entry(@working_dir) if @tmp_working_dir
49
+ end
50
+
51
+ private
52
+
53
+ def write_inventory
54
+ ensure_directory(File.dirname(inventory_file))
55
+ File.write(inventory_file, JSON.dump(@inventory))
56
+ end
57
+
58
+ def write_playbook
59
+ ensure_directory(File.dirname(playbook_file))
60
+ File.write(playbook_file, @playbook)
61
+ end
62
+
63
+ def inventory_file
64
+ File.join(@working_dir, 'foreman-inventories', id)
65
+ end
66
+
67
+ def playbook_file
68
+ File.join(@working_dir, "foreman-playbook-#{id}.yml")
69
+ end
70
+
71
+ def events_dir
72
+ File.join(@working_dir, 'events', id.to_s)
73
+ end
74
+
75
+ def ensure_directory(path)
76
+ if File.exist?(path)
77
+ raise "#{path} expected to be a directory" unless File.directory?(path)
78
+ else
79
+ FileUtils.mkdir_p(path)
80
+ end
81
+ path
82
+ end
83
+
84
+ def initialize_dirs
85
+ settings = ForemanAnsibleCore.settings
86
+ initialize_working_dir(settings[:working_dir])
87
+ initialize_ansible_dir(settings[:ansible_dir])
88
+ end
89
+
90
+ def initialize_working_dir(working_dir)
91
+ if working_dir.nil?
92
+ @working_dir = Dir.mktmpdir
93
+ @tmp_working_dir = true
94
+ else
95
+ @working_dir = File.expand_path(working_dir)
96
+ end
97
+ end
98
+
99
+ def initialize_ansible_dir(ansible_dir)
100
+ raise "Ansible dir #{ansible_dir} does not exist" unless
101
+ !ansible_dir.nil? && File.exist?(ansible_dir)
102
+ @ansible_dir = ansible_dir
103
+ end
104
+
105
+ def unknown_hosts
106
+ @inventory['all']['hosts'].select do |host|
107
+ Net::SSH::KnownHosts.search_for(host).empty?
108
+ end
109
+ end
110
+
111
+ def add_to_known_hosts(host)
112
+ logger.warn("[foreman_ansible] - Host #{host} not found in known_hosts")
113
+ Net::SSH::Transport::Session.new(host).host_keys.each do |host_key|
114
+ Net::SSH::KnownHosts.add(host, host_key)
115
+ end
116
+ logger.warn("[foreman_ansible] - Added host key #{host} to known_hosts")
117
+ rescue StandardError => e
118
+ logger.error('[foreman_ansible] - Failed to save host key for '\
119
+ "#{host}: #{e}")
120
+ end
121
+
122
+ def rebuild_secrets(inventory, secrets)
123
+ inventory['all']['hosts'].each do |name|
124
+ per_host = secrets['per-host'][name]
125
+
126
+ new_secrets = {
127
+ 'ansible_ssh_pass' => inventory['ssh_password'] || per_host['ansible_ssh_pass'],
128
+ 'ansible_sudo_pass' => inventory['sudo_password'] || per_host['ansible_sudo_pass']
129
+ }
130
+ inventory['_meta']['hostvars'][name].update(new_secrets)
131
+ end
132
+
133
+ inventory
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,38 @@
1
+ require 'fileutils'
2
+
3
+ module ForemanAnsibleCore
4
+ module TaskLauncher
5
+ class AnsibleRunner < ForemanTasksCore::TaskLauncher::AbstractGroup
6
+ def runner_input(input)
7
+ super(input).reduce({}) do |acc, (_id, data)|
8
+ acc.merge(data[:input]['action_input']['name'] => data)
9
+ end
10
+ end
11
+
12
+ def operation
13
+ 'ansible-runner'
14
+ end
15
+
16
+ def self.runner_class
17
+ Runner::AnsibleRunner
18
+ end
19
+
20
+ # def self.input_format
21
+ # {
22
+ # $UUID => {
23
+ # :execution_plan_id => $EXECUTION_PLAN_UUID,
24
+ # :run_step_id => Integer,
25
+ # :input => {
26
+ # :action_class => Class,
27
+ # :action_input => {
28
+ # "ansible_inventory"=> String,
29
+ # "hostname"=>"127.0.0.1",
30
+ # "script"=>"---\n- hosts: all\n tasks:\n - shell: |\n true\n register: out\n - debug: var=out"
31
+ # }
32
+ # }
33
+ # }
34
+ # }
35
+ # end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,23 @@
1
+ module ForemanAnsibleCore
2
+ module TaskLauncher
3
+ class Playbook < ForemanTasksCore::TaskLauncher::Batch
4
+ class PlaybookRunnerAction < ForemanTasksCore::Runner::Action
5
+ def initiate_runner
6
+ additional_options = {
7
+ :step_id => run_step_id,
8
+ :uuid => execution_plan_id
9
+ }
10
+ ::ForemanAnsibleCore::RemoteExecutionCore::AnsibleRunner.new(
11
+ input.merge(additional_options),
12
+ :suspended_action => suspended_action
13
+ )
14
+ end
15
+ end
16
+
17
+ def child_launcher(parent)
18
+ ForemanTasksCore::TaskLauncher::Single.new(world, callback, :parent => parent,
19
+ :action_class_override => PlaybookRunnerAction)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ForemanAnsibleCore
4
- VERSION = '2.2.0'
4
+ VERSION = '3.0.3'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_ansible_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 3.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Lobato Garcia
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-22 00:00:00.000000000 Z
11
+ date: 2020-03-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.1'
33
+ version: 0.3.2
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.1'
40
+ version: 0.3.2
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: foreman_remote_execution_core
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -79,11 +79,13 @@ files:
79
79
  - bin/json_inventory.sh
80
80
  - lib/foreman_ansible_core.rb
81
81
  - lib/foreman_ansible_core/actions.rb
82
- - lib/foreman_ansible_core/command_creator.rb
83
82
  - lib/foreman_ansible_core/exception.rb
84
- - lib/foreman_ansible_core/playbook_runner.rb
85
83
  - lib/foreman_ansible_core/remote_execution_core/ansible_runner.rb
86
- - lib/foreman_ansible_core/remote_execution_core/settings_override.rb
84
+ - lib/foreman_ansible_core/runner/ansible_runner.rb
85
+ - lib/foreman_ansible_core/runner/command_creator.rb
86
+ - lib/foreman_ansible_core/runner/playbook.rb
87
+ - lib/foreman_ansible_core/task_launcher/ansible_runner.rb
88
+ - lib/foreman_ansible_core/task_launcher/playbook.rb
87
89
  - lib/foreman_ansible_core/version.rb
88
90
  homepage: https://github.com/theforeman/foreman_ansible
89
91
  licenses:
@@ -104,8 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
106
  - !ruby/object:Gem::Version
105
107
  version: '0'
106
108
  requirements: []
107
- rubyforge_project:
108
- rubygems_version: 2.6.8
109
+ rubygems_version: 3.0.3
109
110
  signing_key:
110
111
  specification_version: 4
111
112
  summary: 'Ansible integration with Foreman (theforeman.org): core bits'
@@ -1,121 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'foreman_tasks_core/runner/command_runner'
4
- require_relative 'command_creator'
5
- require 'tmpdir'
6
- require 'net/ssh'
7
-
8
- module ForemanAnsibleCore
9
- # Implements ForemanTasksCore::Runner::Base interface for running
10
- # Ansible playbooks, used by the Foreman Ansible plugin and Ansible proxy
11
- class PlaybookRunner < ForemanTasksCore::Runner::CommandRunner
12
- attr_reader :command_out, :command_in, :command_pid
13
-
14
- def initialize(inventory, playbook, options = {})
15
- super
16
- @inventory = inventory
17
- unknown_hosts.each do |host|
18
- add_to_known_hosts(host)
19
- end
20
- @playbook = playbook
21
- @options = options
22
- initialize_dirs
23
- end
24
-
25
- def start
26
- write_inventory
27
- write_playbook
28
- command = CommandCreator.new(inventory_file,
29
- playbook_file,
30
- @options).command
31
- logger.debug('[foreman_ansible] - Initializing Ansible Runner')
32
- Dir.chdir(@ansible_dir) do
33
- initialize_command(*command)
34
- logger.debug("[foreman_ansible] - Running command #{command}")
35
- end
36
- end
37
-
38
- def kill
39
- publish_data('== TASK ABORTED BY USER ==', 'stdout')
40
- publish_exit_status(1)
41
- ::Process.kill('SIGTERM', @command_pid)
42
- close
43
- end
44
-
45
- def close
46
- super
47
- FileUtils.remove_entry(@working_dir) if @tmp_working_dir
48
- end
49
-
50
- private
51
-
52
- def write_inventory
53
- ensure_directory(File.dirname(inventory_file))
54
- File.write(inventory_file, @inventory)
55
- end
56
-
57
- def write_playbook
58
- ensure_directory(File.dirname(playbook_file))
59
- File.write(playbook_file, @playbook)
60
- end
61
-
62
- def inventory_file
63
- File.join(@working_dir, 'foreman-inventories', id)
64
- end
65
-
66
- def playbook_file
67
- File.join(@working_dir, "foreman-playbook-#{id}.yml")
68
- end
69
-
70
- def events_dir
71
- File.join(@working_dir, 'events', id.to_s)
72
- end
73
-
74
- def ensure_directory(path)
75
- if File.exist?(path)
76
- raise "#{path} expected to be a directory" unless File.directory?(path)
77
- else
78
- FileUtils.mkdir_p(path)
79
- end
80
- path
81
- end
82
-
83
- def initialize_dirs
84
- settings = ForemanAnsibleCore.settings
85
- initialize_working_dir(settings[:working_dir])
86
- initialize_ansible_dir(settings[:ansible_dir])
87
- end
88
-
89
- def initialize_working_dir(working_dir)
90
- if working_dir.nil?
91
- @working_dir = Dir.mktmpdir
92
- @tmp_working_dir = true
93
- else
94
- @working_dir = File.expand_path(working_dir)
95
- end
96
- end
97
-
98
- def initialize_ansible_dir(ansible_dir)
99
- raise "Ansible dir #{ansible_dir} does not exist" unless
100
- !ansible_dir.nil? && File.exist?(ansible_dir)
101
- @ansible_dir = ansible_dir
102
- end
103
-
104
- def unknown_hosts
105
- JSON.parse(@inventory)['all']['hosts'].select do |host|
106
- Net::SSH::KnownHosts.search_for(host).empty?
107
- end
108
- end
109
-
110
- def add_to_known_hosts(host)
111
- logger.warn("[foreman_ansible] - Host #{host} not found in known_hosts")
112
- Net::SSH::Transport::Session.new(host).host_keys.each do |host_key|
113
- Net::SSH::KnownHosts.add(host, host_key)
114
- end
115
- logger.warn("[foreman_ansible] - Added host key #{host} to known_hosts")
116
- rescue StandardError => e
117
- logger.error('[foreman_ansible] - Failed to save host key for '\
118
- "#{host}: #{e}")
119
- end
120
- end
121
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ForemanAnsibleCore
4
- module RemoteExecutionCore
5
- # Ensure the Ansible provider is used whenever a JobTemplate using this
6
- # provider is called.
7
- module SettingsOverride
8
- def initiate_runner
9
- return super unless input['ansible_inventory']
10
- additional_options = {
11
- :step_id => run_step_id,
12
- :uuid => execution_plan_id
13
- }
14
- ::ForemanAnsibleCore::RemoteExecutionCore::AnsibleRunner.new(
15
- input.merge(additional_options)
16
- )
17
- end
18
- end
19
- end
20
- end