foreman_ansible 10.4.3 → 11.0.0

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: 43677522138ced457422019bc60d466cc4ff22956ce56cf35c6fad5bc6227aae
4
- data.tar.gz: a1523c4616c40ee68cd0209668d34f6a8ae20a817742181ca71f54580b38706f
3
+ metadata.gz: 348701b380a514ccae60dda27305a137438dd4cd2812f9515e071a527a0b20c5
4
+ data.tar.gz: ab770d603437ed890a945381d28411e0caff547f6bef26b22c98191fe6317b98
5
5
  SHA512:
6
- metadata.gz: a513cd384608bf244807afc825d8f0db7e1984fbd1acc836cff5d4a35fbbcdb2163d56dea7927f5ff76c3b49dc3c2d9a84c21a0e0946f821058944054b15ba9a
7
- data.tar.gz: 271871a432184fc08437e02cac8fc5a7389f9cb1a475727d96aa2870fe8beb9b11e35b926771946d48df9e13de34e01130b4294f9b1a54bf6a7644a5fe43559d
6
+ metadata.gz: 0a780ccd49ae7534e43de5ea1f50aab631b3f59c30c5793455e242568b77d2572fe187f7f0c75667cb1c22ccfd03666dd2ce7df2541cb974df1693ff58079250
7
+ data.tar.gz: ab9bdea79a470967e8c6592d7166317668a5d9f892887b8d715fc1daaa9a8ce99959cb5c4da2496dabf4b9e4d2ada5909c2e78bfa250bcd13d2250d7d32a1473
@@ -8,14 +8,12 @@ module Types
8
8
  argument :match, String, required: false
9
9
  end
10
10
 
11
- field :meta, ::Types::Meta
12
-
13
- def meta
11
+ field :meta, ::Types::Meta, resolve: (proc do |object|
14
12
  {
15
13
  :can_edit => ::User.current.can?(object.ansible_variable.permission_name(:edit), object.ansible_variable),
16
14
  :can_destroy => ::User.current.can?(object.ansible_variable.permission_name(:destroy), object.ansible_variable)
17
15
  }
18
- end
16
+ end)
19
17
 
20
18
  def lookup_values(match: nil)
21
19
  return CollectionLoader.for(object.ansible_variable.class, :lookup_values).load(object.ansible_variable) unless match
@@ -3,39 +3,13 @@
3
3
  module ForemanAnsible
4
4
  module AnsibleHostgroupsHelper
5
5
  def ansible_hostgroups_actions(hostgroup)
6
- actions = []
7
- is_hostgroup_empty = hostgroup.all_ansible_roles.empty? || hostgroup.hosts_count.zero?
6
+ play_roles = if hostgroup.all_ansible_roles.empty?
7
+ { action: { content: (link_to _('Run all Ansible roles'), 'javascript:void(0);', disabled: true, title: 'No roles assigned', class: 'disabled'), options: { class: 'disabled' } }, priority: 31 }
8
+ else
9
+ { action: display_link_if_authorized(_('Run all Ansible roles'), hash_for_play_roles_hostgroup_path(id: hostgroup), 'data-no-turbolink': true, title: _('Run all Ansible roles on hosts belonging to this host group')), priority: 31 }
10
+ end
8
11
 
9
- if User.current.can?(:create_job_invocations)
10
- actions << {
11
- action: if is_hostgroup_empty
12
- disabled_action_link(_('Run all Ansible roles'))
13
- else
14
- display_link_if_authorized(_('Run all Ansible roles'), hash_for_play_roles_hostgroup_path(id: hostgroup), 'data-no-turbolink': true, title: _('Run all Ansible roles on hosts belonging to this host group'))
15
- end,
16
- priority: 31
17
- }
18
- end
19
-
20
- if User.current.can?(:view_job_invocations) && User.current.can?(:view_recurring_logics)
21
- actions << {
22
- action: if is_hostgroup_empty
23
- disabled_action_link(_('Configure Ansible Job'))
24
- else
25
- link_to(_('Configure Ansible Job'), "/ansible/hostgroups/#{hostgroup.id}", class: 'la')
26
- end,
27
- priority: 32
28
- }
29
- end
30
-
31
- actions
32
- end
33
-
34
- def disabled_action_link(text)
35
- {
36
- content: link_to(text, 'javascript:void(0);', disabled: true, title: _('No roles/hosts assigned'), class: 'disabled'),
37
- options: { class: 'disabled' }
38
- }
12
+ [play_roles] if User.current.can?(:create_job_invocations)
39
13
  end
40
14
  end
41
15
  end
@@ -28,36 +28,26 @@ module ForemanAnsible
28
28
  def ansible_module_message(log)
29
29
  msg_json = parsed_message_json(log)
30
30
  return _("Execution error: #{msg_json['msg']}") if msg_json['failed'].present?
31
- return msg_json['censored'] if msg_json['censored'].present?
32
31
 
33
- module_action = msg_json.fetch('module', '').delete_prefix('ansible.builtin.').delete_prefix('ansible.legacy.')
32
+ module_action = msg_json['module']
34
33
  case module_action
35
34
  when 'package'
36
35
  msg_json['results'].empty? ? msg_json['msg'] : msg_json['results']
37
36
  when 'template'
38
- get_results(msg_json) do |module_args, result|
39
- _("Rendered template #{module_args['_original_basename']} to #{result['dest']}")
40
- end
37
+ module_args = msg_json['invocation']['module_args']
38
+ _("Rendered template #{module_args['_original_basename']} to #{msg_json['dest']}")
41
39
  when 'service'
42
- get_results(msg_json) do |_, result|
43
- _("Service #{result['name']} #{result['state']} (enabled: #{result['enabled']})")
44
- end
40
+ _("Service #{msg_json['name']} #{msg_json['state']} (enabled: #{msg_json['enabled']})")
45
41
  when 'group'
46
- get_results(msg_json) do |_, result|
47
- _("User group #{result['name']} #{result['state']}, gid: #{result['gid']}")
48
- end
42
+ _("User group #{msg_json['name']} #{msg_json['state']}, gid: #{msg_json['gid']}")
49
43
  when 'user'
50
- get_results(msg_json) do |_, result|
51
- _("User #{result['name']} #{result['state']}, uid: #{result['uid']}")
52
- end
44
+ _("User #{msg_json['name']} #{msg_json['state']}, uid: #{msg_json['uid']}")
53
45
  when 'cron'
54
- get_results(msg_json) do |module_args, _|
55
- _("Cron job: #{module_args['minute']} #{module_args['hour']} #{module_args['day']} #{module_args['month']} #{module_args['weekday']} #{module_args['job']} (disabled: #{module_args['disabled']})")
56
- end
46
+ module_args = msg_json['invocation']['module_args']
47
+ _("Cron job: #{module_args['minute']} #{module_args['hour']} #{module_args['day']} #{module_args['month']} #{module_args['weekday']} #{module_args['job']} (disabled: #{module_args['disabled']})")
57
48
  when 'copy'
58
- get_results(msg_json) do |module_args, result|
59
- _("Copy #{module_args['_original_basename']} to #{result['dest']}")
60
- end
49
+ module_args = msg_json['invocation']['module_args']
50
+ _("Copy #{module_args['_original_basename']} to #{msg_json['dest']}")
61
51
  when 'command', 'shell'
62
52
  msg_json['stdout_lines']
63
53
  else
@@ -79,16 +69,19 @@ module ForemanAnsible
79
69
  false
80
70
  end
81
71
 
82
- private
83
-
84
- def get_results(msg_json)
85
- results = msg_json.key?('results') ? msg_json['results'] : [msg_json]
86
- results.map do |result|
87
- module_args = result.fetch('invocation', {}).fetch('module_args', {})
88
- yield module_args, result
72
+ def show_full_error_message_value(message_value)
73
+ tag.div class: 'replace-hidden-value' do
74
+ link_to_function(icon_text('plus', '', class: 'small'), 'replace_value_control(this, "div")',
75
+ title: _('Show full value'),
76
+ class: 'replace-hidden-value pull-right') +
77
+ (tag.span class: 'full-value' do
78
+ message_value
79
+ end)
89
80
  end
90
81
  end
91
82
 
83
+ private
84
+
92
85
  def parsed_message_json(log)
93
86
  JSON.parse(log.message.value)
94
87
  rescue StandardError => e
@@ -27,13 +27,7 @@ module ForemanAnsible
27
27
  end
28
28
 
29
29
  def proxy_update_button(proxy)
30
- name = if Foreman::Plugin.find('foreman_theme_satellite').present?
31
- :ansible_run_capsule_upgrade
32
- else
33
- :ansible_run_smart_proxy_upgrade
34
- end
35
-
36
- feature = RemoteExecutionFeature.feature(name)
30
+ feature = RemoteExecutionFeature.feature(:ansible_run_capsule_upgrade)
37
31
  return if feature.nil?
38
32
 
39
33
  path = new_job_invocation_path(:host_ids => proxy.infrastructure_host_facets.pluck(:host_id),
@@ -29,8 +29,12 @@
29
29
  <% end %>
30
30
  </ul>
31
31
  <% else %>
32
- <%= log_message %>
33
- <% end %>
32
+ <% allowed_length = 150 %>
33
+ <div class='pull-left'>
34
+ <%= truncate(log_message, length: allowed_length) %>
35
+ </div>
36
+ <%= show_full_error_message_value(log_message) if log_message.length > allowed_length %>
37
+ <% end %>
34
38
  </td>
35
39
  </tr>
36
40
  <% end %>
@@ -1,5 +1,5 @@
1
1
  <%#
2
- name: Capsule Upgrade Playbook
2
+ name: Smart Proxy Upgrade Playbook
3
3
  snippet: false
4
4
  template_inputs:
5
5
  - name: target_version
@@ -26,8 +26,8 @@ feature: ansible_run_capsule_upgrade
26
26
  - hosts: all
27
27
  vars:
28
28
  target_version: "<%= input('target_version').present? ? input('target_version') : product_short_version %>"
29
- tasks:
30
29
  <% if plugin_present?('foreman_theme_satellite') -%>
30
+ tasks:
31
31
  - name: Gather the rpm package facts
32
32
  package_facts:
33
33
  manager: auto
@@ -75,7 +75,35 @@ feature: ansible_run_capsule_upgrade
75
75
  fail:
76
76
  msg: "Failed! Capsule server upgrade failed. See /var/log/foreman-installer/capsule.log in the Capsule server for more information"
77
77
  <% else -%>
78
- - name: Fail if foreman_theme_satellite is missing
78
+ tasks:
79
+ - name: Gather the rpm package facts
80
+ package_facts:
81
+ manager: auto
82
+
83
+ - name: Fail if the target server is a Foreman server
79
84
  fail:
80
- msg: "Failed! The plugin foreman_theme_satellite is not present. This playbook is only for use with Satellite."
85
+ msg: "This playbook cannot be executed on a Foreman server. Use only on a Smart Proxy server."
86
+ when: "'foreman' in ansible_facts.packages"
87
+
88
+ - name: Install foreman release gpg key
89
+ rpm_key:
90
+ state: present
91
+ key: http://yum.theforeman.org/releases/{{ target_version }}/RPM-GPG-KEY-foreman
92
+ when: target_version != "nightly"
93
+
94
+ - name: Update foreman repositories
95
+ package:
96
+ name: https://yum.theforeman.org/releases/{{ target_version }}/el{{ ansible_distribution_major_version }}/{{ ansible_architecture }}/foreman-release.rpm
97
+ state: installed
98
+
99
+ - name: Clean yum metadata
100
+ command: yum clean all
101
+
102
+ - name: Update all packages
103
+ package:
104
+ name: '*'
105
+ state: latest
106
+
107
+ - name: Run the installer
108
+ shell: foreman-installer
81
109
  <% end -%>
@@ -1,5 +1,5 @@
1
1
  class FixAnsibleSettingCategoryToDsl < ActiveRecord::Migration[6.0]
2
2
  def up
3
- Setting.where(category: 'Setting::Ansible').update_all(category: 'Setting') if column_exists?(:settings, :category)
3
+ Setting.where(category: 'Setting::Ansible').update_all(category: 'Setting')
4
4
  end
5
5
  end
@@ -4,7 +4,7 @@ class AddAnsibleCallbackEnabledToTemplates < ActiveRecord::Migration[6.0]
4
4
  def change
5
5
  add_column :templates, :ansible_callback_enabled, :boolean, default: false
6
6
  RemoteExecutionFeature.where(label: 'ansible_run_host').each do |rex_feature|
7
- Template.where(id: rex_feature.job_template_id).update_all(ansible_callback_enabled: true)
7
+ Template.find(rex_feature.job_template_id).update(ansible_callback_enabled: true)
8
8
  end
9
9
  end
10
10
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Foreman::Plugin.register :foreman_ansible do
4
- requires_foreman '>= 3.5'
4
+ requires_foreman '>= 3.6'
5
5
 
6
6
  settings do
7
7
  category :ansible, N_('Ansible') do
@@ -4,5 +4,5 @@
4
4
  # This way other parts of Foreman can just call ForemanAnsible::VERSION
5
5
  # and detect what version the plugin is running.
6
6
  module ForemanAnsible
7
- VERSION = '10.4.3'
7
+ VERSION = '11.0.0'
8
8
  end
data/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "test": "test"
8
8
  },
9
9
  "peerDependencies": {
10
- "@theforeman/vendor": "^10.0"
10
+ "@theforeman/vendor": ">= 8.16.0"
11
11
  },
12
12
  "dependencies": {
13
13
  "react-json-tree": "^0.11.0"
@@ -1,4 +1,4 @@
1
- [{
1
+ {
2
2
  "reporter": "ansible",
3
3
  "reported_at":"2018-01-15 17:31:36 521275",
4
4
  "metrics": {
@@ -24,108 +24,4 @@
24
24
  }
25
25
  }
26
26
  ]
27
- },
28
- {
29
- "reporter": "ansible",
30
- "reported_at":"2022-12-22 10:52:48 521275",
31
- "metrics": {
32
- "time":
33
- { "total":133 }
34
- },
35
- "host": "io.local",
36
- "status": {
37
- "applied": 8,
38
- "failed": 0,
39
- "skipped": 0
40
- },
41
- "logs": [
42
- {
43
- "log": {
44
- "sources": {
45
- "source": "Schedule multiple cronjobs"
46
- },
47
- "messages": {
48
- "message": "{\"changed\": true, \"failed\": false, \"module\": \"cron\", \"msg\": \"All items completed\", \"results\": [{\"_ansible_item_label\": \"date\", \"_ansible_no_log\": false, \"ansible_loop_var\": \"item\", \"changed\": true, \"envs\": [], \"failed\": false, \"invocation\": {\"module_args\": {\"backup\": false, \"cron_file\": null, \"day\": \"*\", \"disabled\": false, \"env\": null, \"hour\": \"5,2\", \"insertafter\": null, \"insertbefore\": null, \"job\": \"date > /dev/null\", \"minute\": \"0\", \"month\": \"*\", \"name\": \"Cron date\", \"reboot\": false, \"special_time\": null, \"state\": \"present\", \"user\": null, \"weekday\": \"*\"}}, \"item\": \"date\", \"jobs\": [\"Cron date\"]}, {\"_ansible_item_label\": \"df\", \"_ansible_no_log\": false, \"ansible_loop_var\": \"item\", \"changed\": true, \"envs\": [], \"failed\": false, \"invocation\": {\"module_args\": {\"backup\": false, \"cron_file\": null, \"day\": \"*\", \"disabled\": false, \"env\": null, \"hour\": \"5,2\", \"insertafter\": null, \"insertbefore\": null, \"job\": \"df > /dev/null\", \"minute\": \"0\", \"month\": \"*\", \"name\": \"Cron df\", \"reboot\": false, \"special_time\": null, \"state\": \"present\", \"user\": null, \"weekday\": \"*\"}}, \"item\": \"df\", \"jobs\": [\"Cron date\", \"Cron df\"]}]}"
49
- },
50
- "level": "notice"
51
- }
52
- },
53
- {
54
- "log": {
55
- "sources": {
56
- "source": "Schedule one cronjob"
57
- },
58
- "messages": {
59
- "message": "{\"_ansible_no_log\": false, \"changed\": true, \"envs\": [], \"failed\": false, \"invocation\": {\"module_args\": {\"backup\": false, \"cron_file\": null, \"day\": \"*\", \"disabled\": false, \"env\": null, \"hour\": \"5,2\", \"insertafter\": null, \"insertbefore\": null, \"job\": \"hostname > /dev/null\", \"minute\": \"0\", \"month\": \"*\", \"name\": \"Schedule hostname\", \"reboot\": false, \"special_time\": null, \"state\": \"present\", \"user\": null, \"weekday\": \"*\"}}, \"jobs\": [\"Cron date\", \"Cron df\", \"Schedule hostname\"], \"module\": \"cron\"}"
60
- },
61
- "level": "notice"
62
- }
63
- },
64
- {
65
- "log": {
66
- "sources": {
67
- "source": "Render multiple templates"
68
- },
69
- "messages": {
70
- "message": "{\"changed\": true, \"failed\": false, \"module\": \"template\", \"msg\": \"All items completed\", \"results\": [{\"_ansible_item_label\": \"test1.txt\", \"_ansible_no_log\": false, \"ansible_loop_var\": \"item\", \"changed\": true, \"checksum\": \"dba7673010f19a94af4345453005933fd511bea9\", \"dest\": \"/tmp/test1.txt\", \"diff\": [], \"failed\": false, \"gid\": 0, \"group\": \"root\", \"invocation\": {\"module_args\": {\"_original_basename\": \"test1.txt.j2\", \"attributes\": null, \"backup\": false, \"checksum\": \"dba7673010f19a94af4345453005933fd511bea9\", \"content\": null, \"delimiter\": null, \"dest\": \"/tmp/test1.txt\", \"directory_mode\": null, \"follow\": false, \"force\": true, \"group\": null, \"local_follow\": null, \"mode\": null, \"owner\": null, \"regexp\": null, \"remote_src\": null, \"selevel\": null, \"serole\": null, \"setype\": null, \"seuser\": null, \"src\": \"/root/.ansible/tmp/ansible-tmp-1671670606.02-7241-175625077259447/source\", \"unsafe_writes\": false, \"validate\": null}}, \"item\": \"test1.txt\", \"md5sum\": null, \"mode\": \"0644\", \"owner\": \"root\", \"secontext\": \"unconfined_u:object_r:admin_home_t:s0\", \"size\": 6, \"src\": \"/root/.ansible/tmp/ansible-tmp-1671670606.02-7241-175625077259447/source\", \"state\": \"file\", \"uid\": 0}, {\"_ansible_item_label\": \"test2.txt\", \"_ansible_no_log\": false, \"ansible_loop_var\": \"item\", \"changed\": true, \"checksum\": \"9054fbe0b622c638224d50d20824d2ff6782e308\", \"dest\": \"/tmp/test2.txt\", \"diff\": [], \"failed\": false, \"gid\": 0, \"group\": \"root\", \"invocation\": {\"module_args\": {\"_original_basename\": \"test2.txt.j2\", \"attributes\": null, \"backup\": false, \"checksum\": \"9054fbe0b622c638224d50d20824d2ff6782e308\", \"content\": null, \"delimiter\": null, \"dest\": \"/tmp/test2.txt\", \"directory_mode\": null, \"follow\": false, \"force\": true, \"group\": null, \"local_follow\": null, \"mode\": null, \"owner\": null, \"regexp\": null, \"remote_src\": null, \"selevel\": null, \"serole\": null, \"setype\": null, \"seuser\": null, \"src\": \"/root/.ansible/tmp/ansible-tmp-1671670620.49-7241-225254470383476/source\", \"unsafe_writes\": false, \"validate\": null}}, \"item\": \"test2.txt\", \"md5sum\": null, \"mode\": \"0644\", \"owner\": \"root\", \"secontext\": \"unconfined_u:object_r:admin_home_t:s0\", \"size\": 6, \"src\": \"/root/.ansible/tmp/ansible-tmp-1671670620.49-7241-225254470383476/source\", \"state\": \"file\", \"uid\": 0}]}"
71
- },
72
- "level": "notice"
73
- }
74
- },
75
- {
76
- "log": {
77
- "sources": {
78
- "source": "Render one template"
79
- },
80
- "messages": {
81
- "message": "{\"_ansible_no_log\": false, \"changed\": true, \"checksum\": \"41c5985fc771b6ecfe8feaa99f8fa9b77ac7d6ce\", \"dest\": \"/tmp/test3.txt\", \"diff\": [], \"failed\": false, \"gid\": 0, \"group\": \"root\", \"invocation\": {\"module_args\": {\"_original_basename\": \"test3.txt.j2\", \"attributes\": null, \"backup\": false, \"checksum\": \"41c5985fc771b6ecfe8feaa99f8fa9b77ac7d6ce\", \"content\": null, \"delimiter\": null, \"dest\": \"/tmp/test3.txt\", \"directory_mode\": null, \"follow\": false, \"force\": true, \"group\": null, \"local_follow\": null, \"mode\": null, \"owner\": null, \"regexp\": null, \"remote_src\": null, \"selevel\": null, \"serole\": null, \"setype\": null, \"seuser\": null, \"src\": \"/root/.ansible/tmp/ansible-tmp-1671670634.79-7306-243717749452063/source\", \"unsafe_writes\": false, \"validate\": null}}, \"md5sum\": null, \"mode\": \"0644\", \"module\": \"template\", \"owner\": \"root\", \"secontext\": \"unconfined_u:object_r:admin_home_t:s0\", \"size\": 6, \"src\": \"/root/.ansible/tmp/ansible-tmp-1671670634.79-7306-243717749452063/source\", \"state\": \"file\", \"uid\": 0}"
82
- },
83
- "level": "notice"
84
- }
85
- },
86
- {
87
- "log": {
88
- "sources": {
89
- "source": "Copy multiple local files"
90
- },
91
- "messages": {
92
- "message": "{\"changed\": true, \"failed\": false, \"module\": \"copy\", \"msg\": \"All items completed\", \"results\": [{\"_ansible_item_label\": \"test4.txt\", \"_ansible_no_log\": false, \"ansible_loop_var\": \"item\", \"changed\": true, \"checksum\": \"ab2649b7e58f7e32b0c75be95d11e2979399d392\", \"dest\": \"/tmp/test4.txt\", \"diff\": [], \"failed\": false, \"gid\": 0, \"group\": \"root\", \"invocation\": {\"module_args\": {\"_original_basename\": \"test4.txt\", \"attributes\": null, \"backup\": false, \"checksum\": \"ab2649b7e58f7e32b0c75be95d11e2979399d392\", \"content\": null, \"delimiter\": null, \"dest\": \"/tmp/test4.txt\", \"directory_mode\": null, \"follow\": false, \"force\": true, \"group\": \"root\", \"local_follow\": null, \"mode\": 256, \"owner\": \"root\", \"regexp\": null, \"remote_src\": null, \"selevel\": null, \"serole\": null, \"setype\": null, \"seuser\": null, \"src\": \"/root/.ansible/tmp/ansible-tmp-1671670648.88-7343-91799014257533/source\", \"unsafe_writes\": false, \"validate\": null}}, \"item\": \"test4.txt\", \"md5sum\": null, \"mode\": \"0400\", \"owner\": \"root\", \"secontext\": \"unconfined_u:object_r:admin_home_t:s0\", \"size\": 6, \"src\": \"/root/.ansible/tmp/ansible-tmp-1671670648.88-7343-91799014257533/source\", \"state\": \"file\", \"uid\": 0}, {\"_ansible_item_label\": \"test5.txt\", \"_ansible_no_log\": false, \"ansible_loop_var\": \"item\", \"changed\": true, \"checksum\": \"4ea77484f3a1c7dde4c0cca2f5c40953388f19f5\", \"dest\": \"/tmp/test5.txt\", \"diff\": [], \"failed\": false, \"gid\": 0, \"group\": \"root\", \"invocation\": {\"module_args\": {\"_original_basename\": \"test5.txt\", \"attributes\": null, \"backup\": false, \"checksum\": \"4ea77484f3a1c7dde4c0cca2f5c40953388f19f5\", \"content\": null, \"delimiter\": null, \"dest\": \"/tmp/test5.txt\", \"directory_mode\": null, \"follow\": false, \"force\": true, \"group\": \"root\", \"local_follow\": null, \"mode\": 256, \"owner\": \"root\", \"regexp\": null, \"remote_src\": null, \"selevel\": null, \"serole\": null, \"setype\": null, \"seuser\": null, \"src\": \"/root/.ansible/tmp/ansible-tmp-1671670662.97-7343-50902792283881/source\", \"unsafe_writes\": false, \"validate\": null}}, \"item\": \"test5.txt\", \"md5sum\": null, \"mode\": \"0400\", \"owner\": \"root\", \"secontext\": \"unconfined_u:object_r:admin_home_t:s0\", \"size\": 6, \"src\": \"/root/.ansible/tmp/ansible-tmp-1671670662.97-7343-50902792283881/source\", \"state\": \"file\", \"uid\": 0}]}"
93
- },
94
- "level": "notice"
95
- }
96
- },
97
- {
98
- "log": {
99
- "sources": {
100
- "source": "Copy one local files"
101
- },
102
- "messages": {
103
- "message": "{\"_ansible_no_log\": false, \"changed\": true, \"checksum\": \"ec4cddb45c3ce640bed61b3d8ab6c18e715dac78\", \"dest\": \"/tmp/test6.txt\", \"diff\": [], \"failed\": false, \"gid\": 0, \"group\": \"root\", \"invocation\": {\"module_args\": {\"_original_basename\": \"test6.txt\", \"attributes\": null, \"backup\": false, \"checksum\": \"ec4cddb45c3ce640bed61b3d8ab6c18e715dac78\", \"content\": null, \"delimiter\": null, \"dest\": \"/tmp/test6.txt\", \"directory_mode\": null, \"follow\": false, \"force\": true, \"group\": \"root\", \"local_follow\": null, \"mode\": 256, \"owner\": \"root\", \"regexp\": null, \"remote_src\": null, \"selevel\": null, \"serole\": null, \"setype\": null, \"seuser\": null, \"src\": \"/root/.ansible/tmp/ansible-tmp-1671670677.05-7408-75605497546833/source\", \"unsafe_writes\": false, \"validate\": null}}, \"md5sum\": null, \"mode\": \"0400\", \"module\": \"copy\", \"owner\": \"root\", \"secontext\": \"unconfined_u:object_r:admin_home_t:s0\", \"size\": 6, \"src\": \"/root/.ansible/tmp/ansible-tmp-1671670677.05-7408-75605497546833/source\", \"state\": \"file\", \"uid\": 0}"
104
- },
105
- "level": "notice"
106
- }
107
- },
108
- {
109
- "log": {
110
- "sources": {
111
- "source": "Restart multiple services"
112
- },
113
- "messages": {
114
- "message": "{\"changed\":true,\"failed\":false,\"module\":\"service\",\"msg\":\"All items completed\",\"results\":[{\"_ansible_item_label\":\"chronyd\",\"_ansible_no_log\":false,\"ansible_loop_var\":\"item\",\"changed\":true,\"failed\":false,\"invocation\":{\"module_args\":{\"daemon_reexec\":false,\"daemon_reload\":false,\"enabled\":null,\"force\":null,\"masked\":null,\"name\":\"chronyd\",\"no_block\":false,\"scope\":null,\"state\":\"restarted\",\"user\":null}},\"item\":\"chronyd\",\"name\":\"chronyd\",\"state\":\"started\"},{\"_ansible_item_label\":\"firewalld\",\"_ansible_no_log\":false,\"ansible_loop_var\":\"item\",\"changed\":true,\"failed\":false,\"invocation\":{\"module_args\":{\"daemon_reexec\":false,\"daemon_reload\":false,\"enabled\":null,\"force\":null,\"masked\":null,\"name\":\"firewalld\",\"no_block\":false,\"scope\":null,\"state\":\"restarted\",\"user\":null}},\"item\":\"firewalld\",\"name\":\"firewalld\",\"state\":\"started\"}]}"
115
- },
116
- "level": "notice"
117
- }
118
- },
119
- {
120
- "log": {
121
- "sources": {
122
- "source": "Restart one service"
123
- },
124
- "messages": {
125
- "message": "{\"_ansible_no_log\":false,\"changed\":true,\"failed\":false,\"invocation\":{\"module_args\":{\"daemon_reexec\":false,\"daemon_reload\":false,\"enabled\":null,\"force\":null,\"masked\":null,\"name\":\"chronyd\",\"no_block\":false,\"scope\":null,\"state\":\"restarted\",\"user\":null}},\"module\":\"service\",\"name\":\"chronyd\",\"state\":\"started\"}"
126
- },
127
- "level": "notice"
128
- }
129
- }
130
- ]
131
- }]
27
+ }
@@ -10,23 +10,21 @@ class HostgroupJsTest < IntegrationTestWithJavascript
10
10
  FactoryBot.create(:host, :hostgroup_id => hostgroup_with_roles.id)
11
11
  end
12
12
 
13
- test 'hostgroup without roles should have disabled links' do
13
+ test 'hostgroup without roles should have disabled link' do
14
14
  visit hostgroups_path(search: hostgroup.name)
15
15
 
16
16
  first_row = page.find('table > tbody > tr:nth-child(1)')
17
17
  first_row.find('td:nth-child(4) > div > a').click
18
18
 
19
19
  assert_includes first(:link, 'Run all Ansible roles')[:class], 'disabled'
20
- assert_includes first(:link, 'Configure Ansible Job')[:class], 'disabled'
21
20
  end
22
21
 
23
- test 'hostgroup with roles should have clickable links' do
22
+ test 'hostgroup with roles should have clickable link' do
24
23
  visit hostgroups_path(search: hostgroup_with_roles.name)
25
24
 
26
25
  first_row = page.find('table > tbody > tr:nth-child(1)')
27
26
  first_row.find('td:nth-child(4) > div > a').click
28
27
 
29
28
  assert_not first(:link, 'Run all Ansible roles')[:class].include?('disabled')
30
- assert_not first(:link, 'Configure Ansible Job')[:class].include?('disabled')
31
29
  end
32
30
  end
@@ -4,15 +4,13 @@ require 'test_plugin_helper'
4
4
 
5
5
  # Tests for the behavior of Host with roles, checks inheritance, etc
6
6
  class ConfigReportExtensionsTest < ActiveSupport::TestCase
7
- let(:example_reports) do
7
+ let(:example_report) do
8
8
  JSON.parse(File.read(ansible_fixture_file('report.json')))
9
9
  end
10
10
 
11
- let(:example_report1) { example_reports.first }
12
-
13
11
  describe '.import' do
14
12
  it 'sets an origin for Ansible reports' do
15
- report = ConfigReport.import(example_report1)
13
+ report = ConfigReport.import(example_report)
16
14
  assert_equal 'Ansible', report.origin
17
15
  end
18
16
 
@@ -20,62 +20,16 @@ ANSIBLELOG
20
20
  )
21
21
  end
22
22
 
23
- test 'module message extraction with action' do
24
- example_report = JSON.parse(File.read(ansible_fixture_file('report.json'))).second
25
- report = ConfigReport.import(example_report)
26
- expected_outputs = [
27
- 'No additional data',
28
- ['Cron job: 0 5,2 * * * date > /dev/null (disabled: false)', 'Cron job: 0 5,2 * * * df > /dev/null (disabled: false)'],
29
- ['Cron job: 0 5,2 * * * hostname > /dev/null (disabled: false)'],
30
- ['Rendered template test1.txt.j2 to /tmp/test1.txt', 'Rendered template test2.txt.j2 to /tmp/test2.txt'],
31
- ['Rendered template test3.txt.j2 to /tmp/test3.txt'],
32
- ['Copy test4.txt to /tmp/test4.txt', 'Copy test5.txt to /tmp/test5.txt'],
33
- ['Copy test6.txt to /tmp/test6.txt'],
34
- ['Service chronyd started (enabled: )', 'Service firewalld started (enabled: )'],
35
- ['Service chronyd started (enabled: )']
36
- ]
37
- actual_outputs = []
38
- report.logs.each do |log|
39
- actual_outputs << ansible_module_message(log)
40
- end
41
- assert_equal expected_outputs, actual_outputs
42
- end
43
-
44
- test 'accepting an almost empty message' do
23
+ test 'module message extraction with error' do
45
24
  log_value = <<-ANSIBLELOG.strip_heredoc
46
- {"changed": true, "failed": false, "module": "copy"}
25
+ {"msg": "AnsibleUndefinedVariable", "changed": false, "_ansible_no_log": false, "failed": true, "module": "template", "exception": "raise AnsibleUndefinedVariable"}
47
26
  ANSIBLELOG
48
27
  message = FactoryBot.build(:message, value: log_value)
49
- log = FactoryBot.build(:log)
28
+ log = FactoryBot.build(:log, message: message)
50
29
  log.message = message
51
- assert_match(
52
- /Copy/,
53
- ansible_module_message(log).to_s
54
- )
55
- end
56
30
 
57
- test 'FQCN module message extraction' do
58
- log_value = <<-ANSIBLELOG.strip_heredoc
59
- {"msg": "Nothing to do", "changed": false, "results": [], "rc": 0, "invocation": {"module_args": {"name": ["openssh"], "state": "present", "allow_downgrade": false, "autoremove": false, "bugfix": false, "disable_gpg_check": false, "disable_plugin": [], "disablerepo": [], "download_only": false, "enable_plugin": [], "enablerepo": [], "exclude": [], "installroot": "/", "install_repoquery": true, "install_weak_deps": true, "security": false, "skip_broken": false, "update_cache": false, "update_only": false, "validate_certs": true, "lock_timeout": 30, "conf_file": null, "disable_excludes": null, "download_dir": null, "list": null, "releasever": null}}, "_ansible_no_log": false, "failed": false, "module": "ansible.builtin.package"}
60
- ANSIBLELOG
61
- message = FactoryBot.build(:message, value: log_value)
62
- log = FactoryBot.build(:log)
63
- log.message = message
64
- assert_match(
65
- /Nothing to do/,
66
- ansible_module_message(log).to_s
67
- )
68
- end
69
-
70
- test 'accepting a censored message' do
71
- log_value = <<-ANSIBLELOG.strip_heredoc
72
- {"censored": "the output has been hidden due to the fact that 'no_log: true' was specified for this result", "changed": true, "failed": false, "module": "copy"}
73
- ANSIBLELOG
74
- message = FactoryBot.build(:message, value: log_value)
75
- log = FactoryBot.build(:log)
76
- log.message = message
77
31
  assert_match(
78
- /output has been hidden/,
32
+ 'Execution error: AnsibleUndefinedVariable',
79
33
  ansible_module_message(log).to_s
80
34
  )
81
35
  end
@@ -86,16 +86,12 @@ const validateRegexp = (variable, value) => {
86
86
  };
87
87
 
88
88
  const validateList = (variable, value) => {
89
- let { validatorRule } = variable;
90
- if (typeof validatorRule !== 'string') {
91
- validatorRule = validatorRule.toString();
92
- }
93
- if (validatorRule.split(',').find(item => item.trim() === value)) {
89
+ if (variable.validatorRule.split(',').find(item => item.trim() === value)) {
94
90
  return validationSuccess;
95
91
  }
96
92
  return {
97
93
  key: 'error',
98
- msg: sprintf(__('Invalid, expected one of: %s'), validatorRule),
94
+ msg: sprintf(__('Invalid, expected one of: %s'), variable.validatorRule),
99
95
  };
100
96
  };
101
97
 
@@ -8,9 +8,4 @@ fragment CurrentUserAttributes on User {
8
8
  name
9
9
  }
10
10
  }
11
- usergroups {
12
- nodes {
13
- admin
14
- }
15
- }
16
11
  }
@@ -11,10 +11,7 @@ export const permissionCheck = (user, permissionsRequired) => {
11
11
  );
12
12
  }
13
13
 
14
- if (
15
- user.admin ||
16
- user.usergroups.nodes.find(usergroup => usergroup.admin === true)
17
- ) {
14
+ if (user.admin) {
18
15
  return { allowed: true };
19
16
  }
20
17
 
@@ -71,9 +71,6 @@ export const userFactory = (login, permissions = []) => ({
71
71
  permissions: {
72
72
  nodes: permissions,
73
73
  },
74
- usergroups: {
75
- nodes: [],
76
- },
77
74
  });
78
75
 
79
76
  export const admin = {
@@ -84,9 +81,6 @@ export const admin = {
84
81
  permissions: {
85
82
  nodes: [],
86
83
  },
87
- usergroups: {
88
- nodes: [],
89
- },
90
84
  };
91
85
 
92
86
  export const intruder = userFactory('intruder', [
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_ansible
3
3
  version: !ruby/object:Gem::Version
4
- version: 10.4.3
4
+ version: 11.0.0
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: 2023-06-13 00:00:00.000000000 Z
11
+ date: 2023-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: acts_as_list
@@ -44,28 +44,28 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '8.2'
47
+ version: '9.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '8.2'
54
+ version: '9.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: foreman-tasks
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '7.1'
61
+ version: '7.0'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '7.1'
68
+ version: '7.0'
69
69
  description: Ansible integration with Foreman
70
70
  email:
71
71
  - elobatocs@gmail.com
@@ -201,7 +201,6 @@ files:
201
201
  - app/views/foreman_ansible/job_templates/run_playbook-ansible_default.erb
202
202
  - app/views/foreman_ansible/job_templates/service_action_-_ansible_default.erb
203
203
  - app/views/foreman_ansible/job_templates/service_action_-_enable_web_console.erb
204
- - app/views/foreman_ansible/job_templates/smart_proxy_upgrade_-_ansible_default.erb
205
204
  - app/views/job_templates/_job_template_callback_tab_content.html.erb
206
205
  - app/views/job_templates/_job_template_callback_tab_headers.html.erb
207
206
  - app/views/ui_ansible_roles/index.json.rabl
@@ -479,16 +478,16 @@ test_files:
479
478
  - test/factories/host_ansible_enhancements.rb
480
479
  - test/fixtures/insights_playbook.yaml
481
480
  - test/fixtures/playbooks_example_output.json
481
+ - test/fixtures/report.json
482
482
  - test/fixtures/sample_facts.json
483
483
  - test/fixtures/sample_playbooks.json
484
- - test/fixtures/report.json
485
484
  - test/foreman_ansible/helpers/ansible_roles_helper_test.rb
486
485
  - test/functional/ansible_roles_controller_test.rb
487
486
  - test/functional/ansible_variables_controller_test.rb
487
+ - test/functional/api/v2/ansible_inventories_controller_test.rb
488
488
  - test/functional/api/v2/ansible_playbooks_controller_test.rb
489
489
  - test/functional/api/v2/ansible_roles_controller_test.rb
490
490
  - test/functional/api/v2/ansible_variables_controller_test.rb
491
- - test/functional/api/v2/ansible_inventories_controller_test.rb
492
491
  - test/functional/api/v2/hostgroups_controller_test.rb
493
492
  - test/functional/api/v2/hosts_controller_test.rb
494
493
  - test/functional/hosts_controller_test.rb
@@ -499,9 +498,9 @@ test_files:
499
498
  - test/test_plugin_helper.rb
500
499
  - test/unit/ansible_role_test.rb
501
500
  - test/unit/ansible_variable_test.rb
501
+ - test/unit/concerns/config_reports_extensions_test.rb
502
502
  - test/unit/concerns/host_managed_extensions_test.rb
503
503
  - test/unit/concerns/hostgroup_extensions_test.rb
504
- - test/unit/concerns/config_reports_extensions_test.rb
505
504
  - test/unit/helpers/ansible_reports_helper_test.rb
506
505
  - test/unit/host_ansible_role_test.rb
507
506
  - test/unit/hostgroup_ansible_role_test.rb
@@ -1,59 +0,0 @@
1
- <%#
2
- name: Smart Proxy Upgrade Playbook
3
- snippet: false
4
- template_inputs:
5
- - name: target_version
6
- required: false
7
- input_type: user
8
- advanced: false
9
- value_type: plain
10
- hidden_value: false
11
- - name: whitelist_options
12
- required: false
13
- input_type: user
14
- advanced: false
15
- value_type: plain
16
- hidden_value: false
17
- model: JobTemplate
18
- job_category: Maintenance Operations
19
- description_format: "%{template_name}"
20
- provider_type: Ansible
21
- kind: job_template
22
- feature: ansible_run_smart_proxy_upgrade
23
- %>
24
-
25
- ---
26
- - hosts: all
27
- vars:
28
- target_version: "<%= input('target_version').present? ? input('target_version') : product_short_version %>"
29
- tasks:
30
- - name: Gather the rpm package facts
31
- package_facts:
32
- manager: auto
33
-
34
- - name: Fail if the target server is a Foreman server
35
- fail:
36
- msg: "This playbook cannot be executed on a Foreman server. Use only on a Smart Proxy server."
37
- when: "'foreman' in ansible_facts.packages"
38
-
39
- - name: Install foreman release gpg key
40
- rpm_key:
41
- state: present
42
- key: http://yum.theforeman.org/releases/{{ target_version }}/RPM-GPG-KEY-foreman
43
- when: target_version != "nightly"
44
-
45
- - name: Update foreman repositories
46
- package:
47
- name: https://yum.theforeman.org/releases/{{ target_version }}/el{{ ansible_distribution_major_version }}/{{ ansible_architecture }}/foreman-release.rpm
48
- state: installed
49
-
50
- - name: Clean yum metadata
51
- command: yum clean all
52
-
53
- - name: Update all packages
54
- package:
55
- name: '*'
56
- state: latest
57
-
58
- - name: Run the installer
59
- shell: foreman-installer