foreman_ansible 6.2.0 → 6.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/ansible_roles_controller.rb +12 -8
  3. data/app/controllers/ansible_variables_controller.rb +4 -0
  4. data/app/controllers/api/v2/ansible_roles_controller.rb +32 -11
  5. data/app/controllers/api/v2/ansible_variables_controller.rb +6 -4
  6. data/app/controllers/foreman_ansible/concerns/import_controller_helper.rb +3 -3
  7. data/app/helpers/foreman_ansible/ansible_reports_helper.rb +8 -0
  8. data/app/helpers/foreman_ansible/ansible_roles_data_preparations.rb +95 -0
  9. data/app/helpers/foreman_ansible/ansible_roles_helper.rb +20 -1
  10. data/app/jobs/sync_roles_and_variables.rb +20 -0
  11. data/app/models/concerns/foreman_ansible/host_managed_extensions.rb +7 -4
  12. data/app/models/concerns/foreman_ansible/hostgroup_extensions.rb +7 -4
  13. data/app/models/foreman_ansible/ansible_provider.rb +2 -1
  14. data/app/models/host_ansible_role.rb +1 -0
  15. data/app/models/hostgroup_ansible_role.rb +1 -0
  16. data/app/models/setting/ansible.rb +9 -0
  17. data/app/services/foreman_ansible/ansible_report_importer.rb +4 -0
  18. data/app/services/foreman_ansible/ansible_report_scanner.rb +15 -1
  19. data/app/services/foreman_ansible/api_roles_importer.rb +23 -11
  20. data/app/services/foreman_ansible/fact_parser.rb +21 -1
  21. data/app/services/foreman_ansible/import_roles_and_variables_error_notification.rb +31 -0
  22. data/app/services/foreman_ansible/import_roles_and_variables_success_notification.rb +26 -0
  23. data/app/services/foreman_ansible/inventory_creator.rb +3 -7
  24. data/app/services/foreman_ansible/roles_importer.rb +3 -2
  25. data/app/services/foreman_ansible/ui_roles_importer.rb +2 -2
  26. data/app/services/foreman_ansible/variables_importer.rb +32 -2
  27. data/app/views/ansible_roles/import.html.erb +10 -50
  28. data/app/views/ansible_variables/index.html.erb +1 -2
  29. data/app/views/api/v2/ansible_roles/sync.json.rabl +5 -0
  30. data/app/views/foreman_ansible/ansible_roles/_select_tab_content.html.erb +1 -2
  31. data/app/views/foreman_ansible/config_reports/_ansible.html.erb +13 -6
  32. data/app/views/foreman_ansible/job_templates/ansible_collections_-_install_from_galaxy.erb +28 -0
  33. data/app/views/foreman_ansible/job_templates/convert_to_rhel.erb +44 -0
  34. data/config/routes.rb +5 -4
  35. data/db/migrate/20210120150019_add_position_to_ansible_role.rb +27 -0
  36. data/db/seeds.d/100_common_parameters.rb +7 -0
  37. data/db/seeds.d/90_notification_blueprints.rb +19 -1
  38. data/lib/foreman_ansible/engine.rb +1 -0
  39. data/lib/foreman_ansible/register.rb +5 -5
  40. data/lib/foreman_ansible/version.rb +1 -1
  41. data/locale/ca/LC_MESSAGES/foreman_ansible.mo +0 -0
  42. data/locale/ca/foreman_ansible.po +1 -1
  43. data/locale/cs_CZ/LC_MESSAGES/foreman_ansible.mo +0 -0
  44. data/locale/cs_CZ/foreman_ansible.po +1 -1
  45. data/locale/de/LC_MESSAGES/foreman_ansible.mo +0 -0
  46. data/locale/de/foreman_ansible.po +1 -1
  47. data/locale/en/LC_MESSAGES/foreman_ansible.mo +0 -0
  48. data/locale/en/foreman_ansible.po +1 -1
  49. data/locale/en_GB/LC_MESSAGES/foreman_ansible.mo +0 -0
  50. data/locale/en_GB/foreman_ansible.po +1 -1
  51. data/locale/es/LC_MESSAGES/foreman_ansible.mo +0 -0
  52. data/locale/es/foreman_ansible.po +1 -1
  53. data/locale/fr/LC_MESSAGES/foreman_ansible.mo +0 -0
  54. data/locale/fr/foreman_ansible.po +1 -1
  55. data/locale/gl/LC_MESSAGES/foreman_ansible.mo +0 -0
  56. data/locale/gl/foreman_ansible.po +1 -1
  57. data/locale/it/LC_MESSAGES/foreman_ansible.mo +0 -0
  58. data/locale/it/foreman_ansible.po +1 -1
  59. data/locale/ja/LC_MESSAGES/foreman_ansible.mo +0 -0
  60. data/locale/ja/foreman_ansible.po +1 -1
  61. data/locale/ko/LC_MESSAGES/foreman_ansible.mo +0 -0
  62. data/locale/ko/foreman_ansible.po +1 -1
  63. data/locale/nl_NL/LC_MESSAGES/foreman_ansible.mo +0 -0
  64. data/locale/nl_NL/foreman_ansible.po +1 -1
  65. data/locale/pl/LC_MESSAGES/foreman_ansible.mo +0 -0
  66. data/locale/pl/foreman_ansible.po +1 -1
  67. data/locale/pt_BR/LC_MESSAGES/foreman_ansible.mo +0 -0
  68. data/locale/pt_BR/foreman_ansible.po +1 -1
  69. data/locale/ru/LC_MESSAGES/foreman_ansible.mo +0 -0
  70. data/locale/ru/foreman_ansible.po +1 -1
  71. data/locale/sv_SE/LC_MESSAGES/foreman_ansible.mo +0 -0
  72. data/locale/sv_SE/foreman_ansible.po +1 -1
  73. data/locale/zh_CN/LC_MESSAGES/foreman_ansible.mo +0 -0
  74. data/locale/zh_CN/foreman_ansible.po +1 -1
  75. data/locale/zh_TW/LC_MESSAGES/foreman_ansible.mo +0 -0
  76. data/locale/zh_TW/foreman_ansible.po +1 -1
  77. data/test/factories/ansible_roles.rb +12 -0
  78. data/test/factories/host_ansible_enhancements.rb +23 -0
  79. data/test/foreman_ansible/helpers/ansible_roles_helper_test.rb +45 -0
  80. data/test/functional/ansible_variables_controller_test.rb +0 -15
  81. data/test/functional/api/v2/ansible_roles_controller_test.rb +23 -0
  82. data/test/functional/api/v2/hostgroups_controller_test.rb +5 -4
  83. data/test/functional/api/v2/hosts_controller_test.rb +9 -8
  84. data/test/functional/hosts_controller_test.rb +10 -6
  85. data/test/unit/concerns/host_managed_extensions_test.rb +17 -3
  86. data/test/unit/concerns/hostgroup_extensions_test.rb +13 -7
  87. data/test/unit/host_ansible_role_test.rb +2 -1
  88. data/test/unit/hostgroup_ansible_role_test.rb +2 -1
  89. data/test/unit/ignore_roles_test.rb +43 -0
  90. data/test/unit/import_roles_and_variables.rb +60 -0
  91. data/test/unit/services/api_roles_importer_test.rb +22 -5
  92. data/test/unit/services/fact_parser_test.rb +16 -0
  93. data/test/unit/services/inventory_creator_test.rb +15 -7
  94. data/test/unit/services/ui_roles_importer_test.rb +2 -2
  95. data/webpack/__mocks__/foremanReact/common/helpers.js +13 -0
  96. data/webpack/__mocks__/foremanReact/components/common/forms/OrderableSelect/helpers.js +5 -0
  97. data/webpack/__mocks__/foremanReact/redux/API.js +7 -0
  98. data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariables.js +178 -0
  99. data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariables.scss +9 -0
  100. data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariablesActions.js +39 -0
  101. data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariablesConstants.js +4 -0
  102. data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariablesHelpers.js +11 -0
  103. data/webpack/components/AnsibleRolesAndVariables/__test__/AnsibleRolesAndVariablesHelpers.test.js +50 -0
  104. data/webpack/components/AnsibleRolesAndVariables/__test__/AnsibleRolesAndVariablesImport.test.js +39 -0
  105. data/webpack/components/AnsibleRolesAndVariables/__test__/__snapshots__/AnsibleRolesAndVariablesImport.test.js.snap +177 -0
  106. data/webpack/components/AnsibleRolesAndVariables/index.js +31 -0
  107. data/webpack/components/AnsibleRolesSwitcher/AnsibleRolesSwitcher.js +14 -18
  108. data/webpack/components/AnsibleRolesSwitcher/AnsibleRolesSwitcher.scss +1 -1
  109. data/webpack/components/AnsibleRolesSwitcher/AnsibleRolesSwitcherActions.js +6 -0
  110. data/webpack/components/AnsibleRolesSwitcher/AnsibleRolesSwitcherConstants.js +1 -2
  111. data/webpack/components/AnsibleRolesSwitcher/AnsibleRolesSwitcherReducer.js +13 -8
  112. data/webpack/components/AnsibleRolesSwitcher/AnsibleRolesSwitcherSelectors.js +8 -28
  113. data/webpack/components/AnsibleRolesSwitcher/__fixtures__/ansibleRolesSwitcherReducer.fixtures.js +1 -0
  114. data/webpack/components/AnsibleRolesSwitcher/__tests__/AnsibleRolesSwitcher.test.js +2 -0
  115. data/webpack/components/AnsibleRolesSwitcher/__tests__/AnsibleRolesSwitcherReducer.test.js +0 -8
  116. data/webpack/components/AnsibleRolesSwitcher/__tests__/AnsibleRolesSwitcherSelectors.test.js +2 -15
  117. data/webpack/components/AnsibleRolesSwitcher/__tests__/__snapshots__/AnsibleRolesSwitcher.test.js.snap +4 -9
  118. data/webpack/components/AnsibleRolesSwitcher/__tests__/__snapshots__/AnsibleRolesSwitcherReducer.test.js.snap +8 -97
  119. data/webpack/components/AnsibleRolesSwitcher/__tests__/__snapshots__/AnsibleRolesSwitcherSelectors.test.js.snap +5 -30
  120. data/webpack/components/AnsibleRolesSwitcher/components/AnsibleRole.js +5 -2
  121. data/webpack/components/AnsibleRolesSwitcher/components/AnsibleRoleInputs.js +43 -0
  122. data/webpack/components/AnsibleRolesSwitcher/components/AnsibleRoleInputs.test.js +19 -0
  123. data/webpack/components/AnsibleRolesSwitcher/components/AssignedRolesList.js +63 -51
  124. data/webpack/components/AnsibleRolesSwitcher/components/AssignedRolesList.test.js +3 -0
  125. data/webpack/components/AnsibleRolesSwitcher/components/OrderedRolesTooltip.js +23 -0
  126. data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AnsibleRoleInputs.test.js.snap +51 -0
  127. data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AssignedRolesList.test.js.snap +28 -28
  128. data/webpack/components/AnsibleRolesSwitcher/index.js +3 -7
  129. data/webpack/index.js +6 -0
  130. metadata +55 -9
  131. data/app/views/ansible_variables/import.html.erb +0 -56
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d95899e15050cbf3f25d75a8f3c9bc5a3059a9dd0ffa90f4690ce84cf49d3408
4
- data.tar.gz: 466754ac90d1e80046fca70ca8db372e90d2b61a0d26a726f0807f7e81227728
3
+ metadata.gz: 3dbc63a3f68609ae8682419576047000d3e815ddfc430e899c93b6f420cdbd8a
4
+ data.tar.gz: ee146c0e155b24635e223ddb0d1ae6693a9921772001f39dbc64eaadde81a075
5
5
  SHA512:
6
- metadata.gz: 9f79b560e9e01e8719c6e705ff5fef6a9f9e7b91bc9ec1b9b79c81750b572c4de6929d2ab07049caefdf4f555a5087c31eb76543d52b87622038107a1e02ea63
7
- data.tar.gz: 357b61ffdb94b61a37ecf87afba07f7e0c2158d4af14d39b701fb31152803692a8feaac09294bb2bc8c0ae8fe8d9daa66eb8eb6f0869c4901315dca688f06dab
6
+ metadata.gz: de0fb54a0b6ef91411c1b09a36d6602bfd11771bd630035596d2ba173c3fc48e258c62e4f7a04c93172ee7f38485be7096ebefe708378b748e8122a5f332729d
7
+ data.tar.gz: 36f23bdd7d722daababf92449772c6bd1be6e4a5b46ad5913b2fa5a37578bd33c149bab9ce3192481d75192b5600d0c13734957c6e97317ff34230043566cb14
@@ -4,7 +4,7 @@
4
4
  class AnsibleRolesController < ::ApplicationController
5
5
  include Foreman::Controller::AutoCompleteSearch
6
6
  include ForemanAnsible::Concerns::ImportControllerHelper
7
-
7
+ include ::ForemanAnsible::AnsibleRolesDataPreparations
8
8
  def index
9
9
  @ansible_roles = resource_base.search_for(params[:search],
10
10
  :order => params[:order]).
@@ -22,18 +22,21 @@ class AnsibleRolesController < ::ApplicationController
22
22
 
23
23
  def import
24
24
  changed = @importer.import!
25
- if changed.values.all?(&:empty?)
25
+ @rows = prepare_ansible_import_rows(changed, @variables_importer)
26
+ if @rows.empty?
26
27
  success no_changed_roles_message
27
28
  redirect_to ansible_roles_path
28
29
  else
29
- render :locals => { :changed => changed }
30
+ render
30
31
  end
31
32
  end
32
33
 
33
34
  def confirm_import
34
- @importer.finish_import(params[:changed]&.to_unsafe_h)
35
- success _('Import of roles successfully finished.')
36
- redirect_to ansible_roles_path
35
+ job = SyncRolesAndVariables.perform_later(params['changed'].to_unsafe_h, @proxy)
36
+ task = ForemanTasks::Task.find_by(external_id: job.provider_job_id)
37
+ render json: {
38
+ task: task
39
+ }, status: :ok
37
40
  end
38
41
 
39
42
  private
@@ -44,10 +47,11 @@ class AnsibleRolesController < ::ApplicationController
44
47
 
45
48
  def create_importer
46
49
  @importer = ForemanAnsible::UiRolesImporter.new(@proxy)
50
+ @variables_importer = ForemanAnsible::VariablesImporter.new(@proxy)
47
51
  end
48
52
 
49
53
  def no_changed_roles_message
50
- return _('No changes in roles detected.') if @proxy.blank?
51
- _('No changes in roles detected on %s.') % @proxy.name
54
+ return _('No added or removed roles nor variables.') if @proxy.blank?
55
+ _('No added or removed roles nor variables detected on %s.') % @proxy.name
52
56
  end
53
57
  end
@@ -104,4 +104,8 @@ class AnsibleVariablesController < ::LookupKeysController
104
104
  end
105
105
  @smart_proxy
106
106
  end
107
+
108
+ def controller_permission
109
+ 'ansible_variables'
110
+ end
107
111
  end
@@ -5,6 +5,7 @@ module Api
5
5
  # API controller for Ansible Roles
6
6
  class AnsibleRolesController < ::Api::V2::BaseController
7
7
  include ::Api::Version2
8
+ include ::ForemanAnsible::AnsibleRolesDataPreparations
8
9
 
9
10
  resource_description do
10
11
  api_version 'v2'
@@ -12,8 +13,8 @@ module Api
12
13
  end
13
14
 
14
15
  before_action :find_resource, :only => [:show, :destroy]
15
- before_action :find_proxy, :only => [:import, :obsolete, :fetch]
16
- before_action :create_importer, :only => [:import, :obsolete, :fetch]
16
+ before_action :find_proxy, :only => [:import, :obsolete, :fetch, :sync]
17
+ before_action :create_importer, :only => [:import, :obsolete, :fetch, :sync]
17
18
 
18
19
  api :GET, '/ansible_roles/:id', N_('Show role')
19
20
  param :id, :identifier, :required => true
@@ -32,28 +33,46 @@ module Api
32
33
  process_response @ansible_role.destroy
33
34
  end
34
35
 
35
- api :PUT, '/ansible_roles/import', N_('Import Ansible roles')
36
+ api :PUT, '/ansible_roles/import', N_('DEPRECATED: Import Ansible roles'), deprecated: true
36
37
  param :proxy_id, :identifier, :required => true, :desc => N_('Smart Proxy to import from')
37
- param :role_names, Array, N_('Ansible role names to import')
38
+ param :role_names, Array, N_('Ansible role names to be imported')
38
39
  def import
39
- @imported = @importer.import!(role_names)
40
+ Foreman::Deprecation.api_deprecation_warning(_('Use sync instead, to sync roles from Smart Proxy with Ansible feature enabled'))
41
+ new_roles = @roles_importer.import_role_names['new']
42
+ if role_names.present?
43
+ new_roles.select! do |role|
44
+ role_names.include?(role.name)
45
+ end
46
+ end
47
+ new_roles.map(&:save)
48
+ @imported = new_roles
49
+ end
50
+
51
+ api :PUT, '/ansible_roles/sync', N_('Sync Ansible roles')
52
+ param :proxy_id, :identifier, :required => true, :desc => N_('Smart Proxy to sync from')
53
+ param :role_names, Array, N_('Ansible role names to be synced')
54
+ def sync
55
+ params = @importer.import!(role_names)
56
+ if params['changed'].present?
57
+ @task = @importer.confirm_sync(params)
58
+ else
59
+ render_message _('No changes detected in specified Ansible Roles and their variables')
60
+ end
40
61
  end
41
62
 
42
- api :PUT, '/ansible_roles/obsolete', N_('Obsolete Ansible roles')
63
+ api :PUT, '/ansible_roles/obsolete', N_('DEPRECATED: Obsolete Ansible roles'), deprecated: true
43
64
  param :proxy_id, :identifier, N_('Smart Proxy to import from')
44
65
  def obsolete
66
+ Foreman::Deprecation.api_deprecation_warning(_('Use sync instead, to sync roles from Smart Proxy with Ansible feature enabled'))
45
67
  @obsoleted = @importer.obsolete!
46
68
  end
47
69
 
48
70
  api :GET, '/ansible_roles/fetch',
49
- N_('Fetch Ansible roles available to be imported')
71
+ N_('Fetch Ansible roles available to be synced')
50
72
  param :proxy_id, :identifier, N_('Smart Proxy to fetch from'),
51
73
  :required => true
52
74
  def fetch
53
- fetched = []
54
- @importer.fetch!.each do |role_name|
55
- fetched << { :name => role_name }
56
- end
75
+ fetched = prepare_ansible_import_rows(@roles_importer.import!, @variables_importer, false)
57
76
  respond_to do |format|
58
77
  format.json do
59
78
  render :json => { :results => { :ansible_roles => fetched } }
@@ -79,6 +98,8 @@ module Api
79
98
  # rubocop:enable Layout/DotPosition
80
99
 
81
100
  def create_importer
101
+ @roles_importer = ForemanAnsible::UiRolesImporter.new(@proxy)
102
+ @variables_importer = ForemanAnsible::VariablesImporter.new(@proxy)
82
103
  @importer = ForemanAnsible::ApiRolesImporter.new(@proxy)
83
104
  end
84
105
  end
@@ -69,20 +69,22 @@ module Api
69
69
  end
70
70
 
71
71
  api :PUT, '/ansible_variables/import',
72
- N_('Import Ansible variables. This will only import variables '\
73
- 'for already existing roles, it will not import any new roles')
72
+ N_('DEPRECATED: Import Ansible variables. This will only import variables '\
73
+ 'for already existing roles, it will not import any new roles'), deprecated: true
74
74
  param :proxy_id, :identifier, N_('Smart Proxy to import from'), :required => true
75
75
  def import
76
+ Foreman::Deprecation.api_deprecation_warning(_('Use sync instead, to sync roles from Smart Proxy with Ansible feature enabled'))
76
77
  new_variables = @importer.import_variable_names([])[:new]
77
78
  new_variables.map(&:save)
78
79
  @imported = new_variables
79
80
  end
80
81
 
81
82
  api :PUT, '/ansible_variables/obsolete',
82
- N_('Obsolete Ansible variables. This will only obsolete variables '\
83
- 'for already existing roles, it will not delete any old roles')
83
+ N_('DEPRECATED: Obsolete Ansible variables. This will only obsolete variables '\
84
+ 'for already existing roles, it will not delete any old roles'), deprecated: true
84
85
  param :proxy_id, :identifier, N_('Smart Proxy to import from'), :required => true
85
86
  def obsolete
87
+ Foreman::Deprecation.api_deprecation_warning(_('Use sync instead, to sync roles from Smart Proxy with Ansible feature enabled'))
86
88
  old_variables = @importer.import_variable_names([])[:obsolete]
87
89
  old_variables.map(&:destroy)
88
90
  @obsoleted = old_variables
@@ -9,15 +9,15 @@ module ForemanAnsible
9
9
  included do
10
10
  # rubocop:disable Rails/LexicallyScopedActionFilter
11
11
  before_action :find_resource, :only => [:destroy]
12
- before_action :find_proxy, :only => [:import]
13
- before_action :create_importer, :only => [:import, :confirm_import]
12
+ before_action :find_proxy, :only => [:import, :import_variables, :confirm_import]
13
+ before_action :create_importer, :only => [:import, :confirm_import, :import_variables, :confirm_import]
14
14
  before_action :default_order, :only => [:index]
15
15
  # rubocop:enable Rails/LexicallyScopedActionFilter
16
16
  end
17
17
 
18
18
  def find_proxy
19
19
  return nil unless params[:proxy]
20
- @proxy = SmartProxy.authorized(:view_smart_proxies).find(params[:proxy])
20
+ @proxy = SmartProxy.find(params[:proxy])
21
21
  end
22
22
  end
23
23
  end
@@ -19,6 +19,14 @@ module ForemanAnsible
19
19
  name
20
20
  end
21
21
 
22
+ def ansible_run_in_check_mode?(log)
23
+ log.message&.value == 'check_mode_enabled' if check_mode_log?(log)
24
+ end
25
+
26
+ def check_mode_log?(log)
27
+ log.source&.value == 'check_mode'
28
+ end
29
+
22
30
  def ansible_module_args(log)
23
31
  report_json_viewer module_invocations parsed_message_json(log)
24
32
  end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanAnsible
4
+ module AnsibleRolesDataPreparations
5
+ VARIABLE_ACTION_NAMES = { 'new' => N_('Add'), 'obsolete' => N_('Remove'), 'update' => N_('Update') }.freeze
6
+ ROLE_ACTION_NAMES = { 'new' => N_('Import Role'), 'obsolete' => N_('Remove Role'), 'old' => N_('Update Role Variables') }.freeze
7
+
8
+ def get_variable_action(kind)
9
+ _(VARIABLE_ACTION_NAMES[kind])
10
+ end
11
+
12
+ def get_role_action(kind)
13
+ _(ROLE_ACTION_NAMES[kind])
14
+ end
15
+
16
+ def get_old_roles_variables(imported_variables, role)
17
+ variables = { 'Add' => [], 'Remove' => [], 'Update' => [] }
18
+ imported_variables.each do |kind, temp_variables|
19
+ temp_variables.each do |temp_variable|
20
+ variables[get_variable_action(kind)].append(temp_variable.key) if temp_variable.ansible_role_id == role.id
21
+ end
22
+ end
23
+ variables
24
+ end
25
+
26
+ def variables_to_s(variables)
27
+ str = ''
28
+ variables.each do |action, temp_variables|
29
+ str += "#{action}: #{temp_variables.size}, " unless temp_variables.empty?
30
+ end
31
+ str[0..-3]
32
+ end
33
+
34
+ def get_roles_variables(imported_variables, variables_importer, kind, role)
35
+ if kind == 'new'
36
+ variables = { 'Add' => variables_importer.get_variables_names(role.name) }
37
+ elsif kind == 'obsolete'
38
+ variables = { 'Remove' => role.ansible_variables.map(&:key) }
39
+ elsif kind == 'old'
40
+ variables = get_old_roles_variables(imported_variables, role)
41
+ end
42
+ variables_to_s(variables)
43
+ end
44
+
45
+ def excluded_roles
46
+ Setting.convert_array_to_regexp(Setting[:ansible_roles_to_ignore])
47
+ end
48
+
49
+ def role_match_excluded_roles(role_name)
50
+ match = role_name.match(excluded_roles)
51
+ match.to_s.empty? ? nil : match
52
+ end
53
+
54
+ def prepare_api_row(role, kind, variables, role_action)
55
+ {
56
+ name: role.name,
57
+ id: role.id,
58
+ role_action: role_action,
59
+ variables: variables,
60
+ hosts_count: role_action == 'Remove Role' ? role.hosts.count : '',
61
+ hostgroup_count: role_action == 'Remove Role' ? role.hostgroups.count : '',
62
+ kind: kind
63
+ }
64
+ end
65
+
66
+ def prepare_ui_row(role, kind, variables, role_action)
67
+ { cells: [
68
+ role.name,
69
+ role_action, variables,
70
+ role_action == 'Remove Role' ? role.hosts.count : '',
71
+ role_action == 'Remove Role' ? role.hostgroups.count : ''
72
+ ],
73
+ role: role, kind: kind, id: role.name }
74
+ end
75
+
76
+ def prepare_ansible_import_rows(changed, variables_importer, is_ui = true)
77
+ rows = []
78
+ changed.each do |kind, roles|
79
+ imported_variables = variables_importer.import_variable_names(roles)
80
+ roles.each do |role|
81
+ next if role_match_excluded_roles(role.name)
82
+ variables = get_roles_variables(imported_variables, variables_importer, kind, role)
83
+ next if variables.empty? && kind['old']
84
+ role_action = get_role_action(kind)
85
+ if is_ui
86
+ rows.append(prepare_ui_row(role, kind, variables, role_action))
87
+ else
88
+ rows.append(prepare_api_row(role, kind, variables, role_action))
89
+ end
90
+ end
91
+ end
92
+ rows
93
+ end
94
+ end
95
+ end
@@ -35,8 +35,27 @@ module ForemanAnsible
35
35
  _('%s ago') % time_ago_in_words(role.updated_at)
36
36
  end
37
37
 
38
+ def role_attributes_for_roles_switcher(form_object)
39
+ inherited_role_ids = form_object.inherited_ansible_roles.map(&:id)
40
+ if form_object.is_a?(Hostgroup)
41
+ assoc_roles = form_object.hostgroup_ansible_roles
42
+ assoc_key = :hostgroup_ansible_role_id
43
+ else
44
+ assoc_roles = form_object.host_ansible_roles
45
+ assoc_key = :host_ansible_role_id
46
+ end
47
+ own_roles_attrs = model_roles_attrs(assoc_roles.reject { |ar| inherited_role_ids.include?(ar.ansible_role_id) }, assoc_key)
48
+ roles_attrs(form_object.inherited_ansible_roles) + own_roles_attrs
49
+ end
50
+
38
51
  def roles_attrs(roles)
39
- roles.map { |item| { :id => item.id, :name => item.name } }
52
+ roles.map { |item| { id: item.id, name: item.name } }
53
+ end
54
+
55
+ private
56
+
57
+ def model_roles_attrs(associated_roles, assoc_key)
58
+ associated_roles.map { |item| { id: item.ansible_role_id, name: item.ansible_role.name, position: item.position }.merge(assoc_key => item.id) }
40
59
  end
41
60
  end
42
61
  end
@@ -0,0 +1,20 @@
1
+ class SyncRolesAndVariables < ::ApplicationJob
2
+ queue_as :default
3
+
4
+ def perform(changed, proxy)
5
+ roles_importer = ForemanAnsible::UiRolesImporter.new(proxy)
6
+ variables_importer = ForemanAnsible::VariablesImporter.new(proxy)
7
+ roles_importer.finish_import(changed)
8
+ variables_importer.import_variables_roles(changed) if changed['new'] || changed['old']
9
+ task = ForemanTasks::Task.where(:external_id => @provider_job_id)[0]
10
+ ForemanAnsible::ImportRolesAndVariablesSuccessNotification.deliver!(task)
11
+ rescue StandardError => e
12
+ task = ForemanTasks::Task.where(:external_id => @provider_job_id)[0]
13
+ notification = ForemanAnsible::ImportRolesAndVariablesErrorNotification.new(e, task)
14
+ notification.deliver!
15
+ end
16
+
17
+ def humanized_name
18
+ _('Import roles And Variables')
19
+ end
20
+ end
@@ -8,9 +8,12 @@ module ForemanAnsible
8
8
  base.instance_eval do
9
9
  include ::ForemanAnsible::Concerns::JobInvocationHelper
10
10
 
11
- has_many :host_ansible_roles, :foreign_key => :host_id
12
- has_many :ansible_roles, :through => :host_ansible_roles,
13
- :dependent => :destroy
11
+ has_many :host_ansible_roles, -> { order('host_ansible_roles.position ASC') }, :foreign_key => :host_id
12
+ accepts_nested_attributes_for :host_ansible_roles, :allow_destroy => true
13
+ has_many :ansible_roles,
14
+ -> { order('host_ansible_roles.position ASC') },
15
+ :through => :host_ansible_roles,
16
+ :dependent => :destroy
14
17
  scoped_search :relation => :ansible_roles, :on => :name,
15
18
  :complete_value => true, :rename => :ansible_role,
16
19
  :only_explicit => true
@@ -47,7 +50,7 @@ module ForemanAnsible
47
50
  end
48
51
 
49
52
  def all_ansible_roles
50
- (ansible_roles + inherited_ansible_roles).uniq
53
+ (inherited_ansible_roles + ansible_roles).uniq
51
54
  end
52
55
 
53
56
  # Class methods we may need to override or add
@@ -7,8 +7,11 @@ module ForemanAnsible
7
7
 
8
8
  included do
9
9
  has_many :hostgroup_ansible_roles, :foreign_key => :hostgroup_id
10
- has_many :ansible_roles, :through => :hostgroup_ansible_roles,
11
- :dependent => :destroy
10
+ has_many :ansible_roles,
11
+ -> { order('hostgroup_ansible_roles.position ASC') },
12
+ :through => :hostgroup_ansible_roles,
13
+ :dependent => :destroy
14
+ accepts_nested_attributes_for :hostgroup_ansible_roles, :allow_destroy => true
12
15
  audit_associations :ansible_roles
13
16
 
14
17
  def inherited_ansible_roles
@@ -24,14 +27,14 @@ module ForemanAnsible
24
27
  end
25
28
 
26
29
  def host_ansible_roles
27
- hosts.all.includes(:ansible_roles).flat_map(&:ansible_roles)
30
+ hosts.includes(:host_ansible_roles).flat_map(&:ansible_roles)
28
31
  end
29
32
 
30
33
  # includes also roles of all assigned hosts, useful to determine if
31
34
  # at least one host in this hostgroup has some ansible role assigned
32
35
  # either directly or through hostgroup
33
36
  def all_ansible_roles
34
- (ansible_roles + inherited_ansible_roles + host_ansible_roles).uniq
37
+ (inherited_ansible_roles + ansible_roles + host_ansible_roles).uniq
35
38
  end
36
39
  end
37
40
  end
@@ -27,7 +27,8 @@ if defined? ForemanRemoteExecution
27
27
  :remote_execution_command => ansible_command?(
28
28
  template_invocation.template
29
29
  ),
30
- :name => host.name
30
+ :name => host.name,
31
+ :check_mode => host.host_param('ansible_roles_check_mode')
31
32
  )
32
33
  end
33
34
 
@@ -4,6 +4,7 @@
4
4
  class HostAnsibleRole < ApplicationRecord
5
5
  belongs_to_host
6
6
  belongs_to :ansible_role
7
+ acts_as_list scope: :host
7
8
 
8
9
  validates :ansible_role_id, :presence => true,
9
10
  :uniqueness => { :scope => :host_id }
@@ -4,6 +4,7 @@
4
4
  class HostgroupAnsibleRole < ApplicationRecord
5
5
  belongs_to :hostgroup
6
6
  belongs_to :ansible_role
7
+ acts_as_list scope: :hostgroup
7
8
 
8
9
  validates :ansible_role_id, :presence => true,
9
10
  :uniqueness => { :scope => :hostgroup_id }