smart_proxy_ansible 3.6.0 → 3.6.1

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
2
  SHA256:
3
- metadata.gz: c94b0334ddc75bab338d79841ac4cc17d813b5f40c5e06c6f739cfd531d88320
4
- data.tar.gz: bcf96f811ef107f4737bfa5f37ee9f2ac757bf50ac4a7b64b3e8c31397f60fc0
3
+ metadata.gz: 10b497d0820ed673dd5a1c22eee9340f412b8da5da5cfcf592d7c95f1f61b971
4
+ data.tar.gz: eef960a9a5e56832222fabba46c0fd6f413f22d5007bd8c70d9939bc1553b76e
5
5
  SHA512:
6
- metadata.gz: f4f41d9c0a2875c5f33d245d8fec3fb8a15b457102c344bd20bd801e54911de91eabdced4816c968b3ce655ebae3e9292a822f2d75d57553c073aee93e4ac1a6
7
- data.tar.gz: 8fbbf65cb55fc9082ed7194fee478f8334a15a90a1ab3302fef22cde827e920dce29aac775b374b2ba5d651240425c233a08ec72fe6404329137b148aa453e85
6
+ metadata.gz: 3133b0693041281d4c2d657fa762e414732e987a938e353a64444b3951265933634a7da8623b09680fae648a41b8650061058f5392e2d320d1737c510ba0148d
7
+ data.tar.gz: 7d59d08e818ad2ee5dbd280fbb10cc2b523c7d9f1accaa800e949f23fef13e9ff5efd03aa380488e8a7de247ed2b708a5372fda0926922a9cf037a665233d196
@@ -23,11 +23,13 @@ module Proxy::Ansible
23
23
  @rex_command = action_input[:remote_execution_command]
24
24
  @check_mode = action_input[:check_mode]
25
25
  @job_check_mode = action_input[:job_check_mode]
26
+ @diff_mode = action_input[:diff_mode]
26
27
  @tags = action_input[:tags]
27
28
  @tags_flag = action_input[:tags_flag]
28
29
  @passphrase = action_input['secrets']['key_passphrase']
29
30
  @execution_timeout_interval = action_input[:execution_timeout_interval]
30
31
  @cleanup_working_dirs = action_input.fetch(:cleanup_working_dirs, true)
32
+ prune_known_hosts_on_first_execution
31
33
  end
32
34
 
33
35
  def start
@@ -214,7 +216,7 @@ module Proxy::Ansible
214
216
  end
215
217
 
216
218
  def cmdline
217
- cmd_args = [tags_cmd, check_cmd].reject(&:empty?)
219
+ cmd_args = [tags_cmd, check_cmd, diff_cmd].reject(&:empty?)
218
220
  return nil unless cmd_args.any?
219
221
  cmd_args.join(' ')
220
222
  end
@@ -232,6 +234,10 @@ module Proxy::Ansible
232
234
  end
233
235
  end
234
236
 
237
+ def diff_cmd
238
+ diff_mode? ? '"--diff"' : ''
239
+ end
240
+
235
241
  def verbosity
236
242
  '-' + 'v' * @verbosity_level.to_i
237
243
  end
@@ -248,6 +254,10 @@ module Proxy::Ansible
248
254
  @job_check_mode == true
249
255
  end
250
256
 
257
+ def diff_mode?
258
+ @diff_mode == true
259
+ end
260
+
251
261
  def prepare_directory_structure
252
262
  inner = %w[inventory project env].map { |part| File.join(@root, part) }
253
263
  ([@root] + inner).each do |path|
@@ -261,21 +271,40 @@ module Proxy::Ansible
261
271
  logger.debug("[foreman_ansible] - handling event #{description}: #{JSON.pretty_generate(event)}") if logger.level <= ::Logger::DEBUG
262
272
  end
263
273
 
264
- # Each per-host task has inventory only for itself, we must
265
- # collect all the partial inventories into one large inventory
266
- # containing all the hosts.
274
+ # Rebuilds a unified Ansible inventory from multiple per-host inventories.
275
+ # @param input [Hash] The input hash mapping hostnames to inventory data.
276
+ # @return [Hash] The merged inventory.
267
277
  def rebuild_inventory(input)
268
- action_inputs = input.values.map { |hash| hash[:input][:action_input] }
269
- inventories = action_inputs.map { |hash| hash[:ansible_inventory] }
270
- host_vars = inventories.map { |i| i['_meta']['hostvars'] }.reduce({}) do |acc, hosts|
271
- hosts.reduce(acc) do |inner_acc, (hostname, vars)|
278
+ action_inputs = input.values.map { |entry| entry['input']['action_input'] }
279
+ inventories = action_inputs.map { |action_input| action_input['ansible_inventory'] }
280
+ first_execution_by_host = action_inputs.to_h { |action_input| [action_input['name'], action_input['first_execution']] }
281
+
282
+ host_vars = merge_hostvars_from_inventories(inventories)
283
+
284
+ # Use the first inventory's group vars as a base, fallback to empty hash if missing
285
+ group_vars = inventories.first.dig('all', 'vars') || {}
286
+
287
+ inventory = {
288
+ 'all' => {
289
+ 'hosts' => host_vars,
290
+ 'vars' => group_vars
291
+ }
292
+ }
293
+
294
+ update_first_execution_flags(inventory['all']['hosts'], first_execution_by_host)
295
+
296
+ inventory
297
+ end
298
+
299
+ # Helper: Merges hostvars from a list of inventories, ensuring ssh key is set.
300
+ def merge_hostvars_from_inventories(inventories)
301
+ inventories.each_with_object({}) do |inventory, acc|
302
+ inventory.dig('_meta', 'hostvars')&.each do |hostname, vars|
303
+ # Ensure the ssh key is set for each host
272
304
  vars[:ansible_ssh_private_key_file] ||= Proxy::RemoteExecution::Ssh::Plugin.settings[:ssh_identity_key_file]
273
- inner_acc.merge(hostname => vars)
305
+ acc[hostname] = vars
274
306
  end
275
307
  end
276
-
277
- { 'all' => { 'hosts' => host_vars,
278
- 'vars' => inventories.first['all']['vars'] } }
279
308
  end
280
309
 
281
310
  def working_dir
@@ -303,6 +332,57 @@ module Proxy::Ansible
303
332
 
304
333
  inventory
305
334
  end
335
+
336
+ # Removes known hosts entries for hosts marked as 'first_execution' in the inventory.
337
+ # This ensures SSH host key checking does not fail on first connection.
338
+ # @return [void]
339
+ def prune_known_hosts_on_first_execution
340
+ @inventory.dig('all', 'hosts')&.each_value do |host_data|
341
+ next unless host_data.dig("foreman", "first_execution")
342
+
343
+ interface = host_data.dig("foreman", "foreman_interfaces", 0)
344
+ next unless interface
345
+
346
+ extract_host_identifiers(interface, host_data).each do |host|
347
+ extract_ports(host_data).each do |port|
348
+ Proxy::RemoteExecution::Utils.prune_known_hosts!(host, port, logger)
349
+ end
350
+ end
351
+ end
352
+ end
353
+
354
+ private
355
+
356
+ # Updates the 'first_execution' flag in the foreman data for each host in the inventory.
357
+ # @param hosts [Hash] hostname => host data hash
358
+ # @param execution_flags [Hash] hostname => boolean (first_execution)
359
+ # @return [void]
360
+ def update_first_execution_flags(hosts, execution_flags)
361
+ hosts.each do |hostname, vars|
362
+ foreman = vars['foreman']
363
+ next unless foreman
364
+
365
+ if execution_flags.key?(hostname)
366
+ foreman['first_execution'] = execution_flags[hostname]
367
+ end
368
+ end
369
+ end
370
+
371
+ def extract_host_identifiers(interface, host_data)
372
+ [
373
+ interface["ip"],
374
+ interface["ip6"],
375
+ host_data["ansible_host"],
376
+ interface["name"]
377
+ ].compact.uniq
378
+ end
379
+
380
+ def extract_ports(host_data)
381
+ [
382
+ host_data["ansible_ssh_port"],
383
+ host_data["ansible_port"]
384
+ ].compact.uniq
385
+ end
306
386
  end
307
387
  end
308
388
  end
@@ -2,6 +2,6 @@ module Proxy
2
2
  # Version, this allows the proxy and other plugins know
3
3
  # what version of the Ansible plugin is running
4
4
  module Ansible
5
- VERSION = '3.6.0'
5
+ VERSION = '3.6.1'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_proxy_ansible
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.0
4
+ version: 3.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Nečas
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2025-05-08 00:00:00.000000000 Z
12
+ date: 2025-07-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -45,14 +45,14 @@ dependencies:
45
45
  requirements:
46
46
  - - "~>"
47
47
  - !ruby/object:Gem::Version
48
- version: '0.4'
48
+ version: '0.5'
49
49
  type: :runtime
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
53
  - - "~>"
54
54
  - !ruby/object:Gem::Version
55
- version: '0.4'
55
+ version: '0.5'
56
56
  description: " Smart-Proxy ansible plugin\n"
57
57
  email:
58
58
  - inecas@redhat.com