foreman_ansible 6.3.3 → 7.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/api/v2/ansible_inventories_controller.rb +1 -1
- data/app/graphql/mutations/ansible_variable_overrides/create.rb +26 -0
- data/app/graphql/mutations/ansible_variable_overrides/delete.rb +38 -0
- data/app/graphql/mutations/ansible_variable_overrides/update.rb +26 -0
- data/app/graphql/mutations/hosts/assign_ansible_roles.rb +37 -0
- data/app/graphql/presenters/ansible_role_presenter.rb +12 -0
- data/app/graphql/presenters/overriden_ansible_variable_presenter.rb +19 -0
- data/app/graphql/types/ansible_role.rb +9 -0
- data/app/graphql/types/ansible_variable.rb +23 -0
- data/app/graphql/types/ansible_variable_override.rb +9 -0
- data/app/graphql/types/inherited_ansible_role.rb +13 -0
- data/app/graphql/types/overriden_ansible_variable.rb +27 -0
- data/app/helpers/foreman_ansible/ansible_reports_helper.rb +35 -54
- data/app/models/concerns/foreman_ansible/host_managed_extensions.rb +23 -4
- data/app/models/concerns/foreman_ansible/hostgroup_extensions.rb +1 -0
- data/app/models/foreman_ansible/ansible_provider.rb +56 -6
- data/app/services/foreman_ansible/ansible_report_importer.rb +2 -2
- data/app/services/foreman_ansible/inventory_creator.rb +1 -1
- data/app/services/foreman_ansible/override_resolver.rb +22 -0
- data/app/views/api/v2/ansible_override_values/index.json.rabl +3 -0
- data/app/views/api/v2/ansible_variables/show.json.rabl +1 -1
- data/app/views/foreman_ansible/ansible_roles/_hostgroup_ansible_roles_button.erb +3 -0
- data/app/views/foreman_ansible/config_reports/_ansible.html.erb +14 -5
- data/app/views/foreman_ansible/job_templates/ansible_roles_-_ansible_default.erb +4 -0
- data/app/views/foreman_ansible/job_templates/convert_to_rhel.erb +6 -2
- data/app/views/foreman_ansible/job_templates/run_openscap_scans_-_ansible_default.erb +20 -0
- data/config/routes.rb +3 -0
- data/db/migrate/20210818083407_fix_ansible_setting_category_to_dsl.rb +5 -0
- data/lib/foreman_ansible/engine.rb +0 -18
- data/lib/foreman_ansible/register.rb +114 -2
- data/lib/foreman_ansible/version.rb +1 -1
- data/package.json +10 -6
- data/test/functional/api/v2/ansible_inventories_controller_test.rb +1 -2
- data/test/graphql/mutations/hosts/assign_ansible_roles_mutation_test.rb +96 -0
- data/test/graphql/queries/ansible_roles_query_test.rb +35 -0
- data/test/unit/ansible_provider_test.rb +3 -6
- data/test/unit/concerns/host_managed_extensions_test.rb +8 -0
- data/test/unit/concerns/hostgroup_extensions_test.rb +6 -0
- data/test/unit/helpers/ansible_reports_helper_test.rb +4 -30
- data/test/unit/services/override_resolver_test.rb +34 -0
- data/webpack/components/AnsibleHostDetail/AnsibleHostDetail.js +59 -0
- data/webpack/components/AnsibleHostDetail/AnsibleHostDetail.scss +6 -0
- data/webpack/components/AnsibleHostDetail/AnsibleHostDetail.test.js +20 -0
- data/webpack/components/AnsibleHostDetail/components/AnsibleHostInventory/AnsibleHostInventory.js +22 -0
- data/webpack/components/AnsibleHostDetail/components/AnsibleHostInventory/AnsibleHostInventory.scss +4 -0
- data/webpack/components/AnsibleHostDetail/components/AnsibleHostInventory/AnsibleHostInventory.test.js +104 -0
- data/webpack/components/AnsibleHostDetail/components/AnsibleHostInventory/index.js +38 -0
- data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/AnsibleVariableOverrides.scss +3 -0
- data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/AnsibleVariableOverridesTable.js +238 -0
- data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/AnsibleVariableOverridesTableHelper.js +111 -0
- data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/EditableAction.js +161 -0
- data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/EditableAction.scss +7 -0
- data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/EditableActionHelper.js +49 -0
- data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/EditableValue.js +70 -0
- data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/EditableValueHelper.js +35 -0
- data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/__test__/AnsibleVariableOverrides.fixtures.js +429 -0
- data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/__test__/AnsibleVariableOverrides.test.js +71 -0
- data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/__test__/AnsibleVariableOverridesDelete.test.js +74 -0
- data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/__test__/AnsibleVariableOverridesUpdate.test.js +188 -0
- data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/index.js +58 -0
- data/webpack/components/AnsibleHostDetail/components/JobsTab/JobsTabHelper.js +79 -0
- data/webpack/components/AnsibleHostDetail/components/JobsTab/NewRecurringJobHelper.js +106 -0
- data/webpack/components/AnsibleHostDetail/components/JobsTab/NewRecurringJobModal.js +129 -0
- data/webpack/components/AnsibleHostDetail/components/JobsTab/NewRecurringJobModal.scss +7 -0
- data/webpack/components/AnsibleHostDetail/components/JobsTab/PreviousJobsTable.js +103 -0
- data/webpack/components/AnsibleHostDetail/components/JobsTab/RecurringJobsTable.js +96 -0
- data/webpack/components/AnsibleHostDetail/components/JobsTab/__test__/JobsTab.fixtures.js +184 -0
- data/webpack/components/AnsibleHostDetail/components/JobsTab/__test__/JobsTab.test.js +195 -0
- data/webpack/components/AnsibleHostDetail/components/JobsTab/index.js +88 -0
- data/webpack/components/AnsibleHostDetail/components/RolesTab/AllRolesModal/AllRolesTable.js +89 -0
- data/webpack/components/AnsibleHostDetail/components/RolesTab/AllRolesModal/index.js +80 -0
- data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/EditRolesForm.js +90 -0
- data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/EditRolesModal.scss +3 -0
- data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/EditRolesModalHelper.js +40 -0
- data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/index.js +82 -0
- data/webpack/components/AnsibleHostDetail/components/RolesTab/RolesTable.js +129 -0
- data/webpack/components/AnsibleHostDetail/components/RolesTab/__test__/EditRoles.test.js +85 -0
- data/webpack/components/AnsibleHostDetail/components/RolesTab/__test__/RolesTab.fixtures.js +180 -0
- data/webpack/components/AnsibleHostDetail/components/RolesTab/__test__/RolesTab.test.js +75 -0
- data/webpack/components/AnsibleHostDetail/components/RolesTab/index.js +51 -0
- data/webpack/components/AnsibleHostDetail/components/SecondaryTabRoutes.js +60 -0
- data/webpack/components/AnsibleHostDetail/components/TabLayout.js +12 -0
- data/webpack/components/AnsibleHostDetail/constants.js +9 -0
- data/webpack/components/AnsibleHostDetail/helpers.js +4 -0
- data/webpack/components/AnsibleHostDetail/index.js +6 -0
- data/webpack/components/AnsibleRolesAndVariables/__test__/AnsibleRolesAndVariablesImport.test.js +15 -10
- data/webpack/components/AnsibleRolesSwitcher/components/AnsibleRole.js +29 -0
- data/webpack/components/AnsibleRolesSwitcher/components/AnsibleRole.test.js +3 -0
- data/webpack/components/AnsibleRolesSwitcher/components/AvailableRolesList.js +2 -1
- data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AnsiblePermissionDenied.test.js.snap +2 -0
- data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AnsibleRole.test.js.snap +3 -3
- data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AssignedRolesList.test.js.snap +4 -4
- data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AvailableRolesList.test.js.snap +9 -0
- data/webpack/components/DualList/DualList.scss +3 -0
- data/webpack/components/DualList/ListControls.js +65 -0
- data/webpack/components/DualList/ListHeader.js +16 -0
- data/webpack/components/DualList/ListItem.js +69 -0
- data/webpack/components/DualList/ListPane.js +95 -0
- data/webpack/components/DualList/SelectedStatus.js +21 -0
- data/webpack/components/DualList/index.js +103 -0
- data/webpack/components/ErrorState.js +16 -0
- data/webpack/components/withLoading.js +135 -0
- data/webpack/components/withPagination.js +0 -0
- data/webpack/formHelper.js +131 -0
- data/webpack/globalIdHelper.js +13 -0
- data/webpack/global_index.js +18 -0
- data/webpack/graphql/mutations/assignAnsibleRoles.gql +17 -0
- data/webpack/graphql/mutations/cancelRecurringLogic.gql +12 -0
- data/webpack/graphql/mutations/createAnsibleVariableOverride.gql +28 -0
- data/webpack/graphql/mutations/createJobInvocation.gql +11 -0
- data/webpack/graphql/mutations/deleteAnsibleVariableOverride.gql +17 -0
- data/webpack/graphql/mutations/updateAnsibleVariableOverride.gql +29 -0
- data/webpack/graphql/queries/allAnsibleRoles.gql +13 -0
- data/webpack/graphql/queries/ansibleRoles.gql +13 -0
- data/webpack/graphql/queries/currentUserAttributes.gql +11 -0
- data/webpack/graphql/queries/hostAnsibleRoles.gql +17 -0
- data/webpack/graphql/queries/hostAvailableAnsibleRoles.gql +11 -0
- data/webpack/graphql/queries/hostVariableOverrides.gql +39 -0
- data/webpack/graphql/queries/recurringJobs.gql +28 -0
- data/webpack/helpers/pageParamsHelper.js +40 -0
- data/webpack/helpers/paginationHelper.js +9 -0
- data/webpack/permissionsHelper.js +58 -0
- data/webpack/routes/HostgroupJobs/__test__/HostgroupJobs.fixtures.js +63 -0
- data/webpack/routes/HostgroupJobs/__test__/HostgroupJobs.test.js +112 -0
- data/webpack/routes/HostgroupJobs/index.js +26 -0
- data/webpack/routes/routes.js +10 -0
- data/webpack/testHelper.js +165 -0
- data/webpack/toastHelper.js +4 -0
- metadata +130 -78
- data/app/assets/images/foreman_ansible/Ansible.png +0 -0
- data/app/models/foreman_ansible/fact_name.rb +0 -16
- data/app/models/setting/ansible.rb +0 -106
- data/app/services/foreman_ansible/fact_importer.rb +0 -99
- data/app/services/foreman_ansible/fact_parser.rb +0 -126
- data/app/services/foreman_ansible/fact_sparser.rb +0 -37
- data/app/services/foreman_ansible/operating_system_parser.rb +0 -102
- data/app/services/foreman_ansible/structured_fact_importer.rb +0 -25
- data/test/unit/lib/foreman_ansible_core/ansible_runner_test.rb +0 -51
- data/test/unit/lib/foreman_ansible_core/command_creator_test.rb +0 -64
- data/test/unit/lib/foreman_ansible_core/playbook_runner_test.rb +0 -110
- data/test/unit/services/fact_importer_test.rb +0 -52
- data/test/unit/services/fact_parser_test.rb +0 -281
- data/test/unit/services/fact_sparser_test.rb +0 -24
- data/test/unit/services/structured_fact_importer_test.rb +0 -30
- data/webpack/__mocks__/foremanReact/common/I18n.js +0 -1
- data/webpack/__mocks__/foremanReact/common/helpers.js +0 -13
- data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +0 -2
- data/webpack/__mocks__/foremanReact/components/common/EmptyState.js +0 -5
- data/webpack/__mocks__/foremanReact/components/common/forms/OrderableSelect/helpers.js +0 -5
- data/webpack/__mocks__/foremanReact/redux/API.js +0 -7
- data/webpack/components/AnsibleRolesAndVariables/__test__/__snapshots__/AnsibleRolesAndVariablesImport.test.js.snap +0 -177
@@ -10,8 +10,7 @@
|
|
10
10
|
<thead>
|
11
11
|
<tr>
|
12
12
|
<th><%= _("Level") %></th>
|
13
|
-
<th><%= _("
|
14
|
-
<th><%= _("Arguments") %></th>
|
13
|
+
<th><%= _("Task") %></th>
|
15
14
|
<th><%= _("Message") %></th>
|
16
15
|
</tr>
|
17
16
|
</thead>
|
@@ -20,9 +19,19 @@
|
|
20
19
|
<% unless check_mode_log?(log) %>
|
21
20
|
<tr>
|
22
21
|
<td><span <%= report_tag log.level %>><%= h log.level %></span></td>
|
23
|
-
<td
|
24
|
-
<td
|
25
|
-
|
22
|
+
<td><span title=<%= ansible_module_name(log) %>><%= ansible_task_name(log) %></span></td>
|
23
|
+
<td>
|
24
|
+
<% log_message = ansible_module_message(log) %>
|
25
|
+
<% if log_message.is_a? Array %>
|
26
|
+
<ul>
|
27
|
+
<% log_message.each do |message_line| %>
|
28
|
+
<li><%= message_line %></li>
|
29
|
+
<% end %>
|
30
|
+
</ul>
|
31
|
+
<% else %>
|
32
|
+
<%= log_message %>
|
33
|
+
<% end %>
|
34
|
+
</td>
|
26
35
|
</tr>
|
27
36
|
<% end %>
|
28
37
|
<% end %>
|
@@ -15,10 +15,14 @@ model: JobTemplate
|
|
15
15
|
- name: Display all parameters known for the Foreman host
|
16
16
|
debug:
|
17
17
|
var: foreman
|
18
|
+
tags:
|
19
|
+
- always
|
18
20
|
tasks:
|
19
21
|
- name: Apply roles
|
20
22
|
include_role:
|
21
23
|
name: "{{ role }}"
|
24
|
+
tags:
|
25
|
+
- always
|
22
26
|
loop: "{{ foreman_ansible_roles }}"
|
23
27
|
loop_control:
|
24
28
|
loop_var: role
|
@@ -5,13 +5,17 @@ template_inputs:
|
|
5
5
|
- name: Activation Key
|
6
6
|
required: true
|
7
7
|
input_type: user
|
8
|
+
description: Set the activation key to assign the desired RHEL subscription and
|
9
|
+
life cycle environment to the converted machine at the registration step.
|
8
10
|
advanced: false
|
9
|
-
value_type:
|
11
|
+
value_type: resource
|
10
12
|
resource_type: Katello::ActivationKey
|
11
13
|
hidden_value: false
|
12
14
|
- name: Restart
|
13
15
|
required: true
|
14
16
|
input_type: user
|
17
|
+
description: Restart the system when it is successfully converted to RHEL to boot
|
18
|
+
the new RHEL kernel.
|
15
19
|
options: "yes\r\nno"
|
16
20
|
advanced: false
|
17
21
|
value_type: plain
|
@@ -34,7 +38,7 @@ kind: job_template
|
|
34
38
|
url: <%= subscription_manager_configuration_url(@host) %>
|
35
39
|
dest: /usr/share/convert2rhel/subscription-manager/katello-ca-consumer-latest.noarch.rpm
|
36
40
|
- name: Start convert2rhel
|
37
|
-
command: convert2rhel -y --activationkey "<%=
|
41
|
+
command: convert2rhel -y --activationkey "<%= input_resource('Activation Key').name %>" --org "<%= @host.organization.label %>" --keep-rhsm
|
38
42
|
<%- if input('Restart') == "yes" -%>
|
39
43
|
- name: Reboot the machine
|
40
44
|
reboot:
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<%#
|
2
|
+
name: Run OpenSCAP scans - Ansible Default
|
3
|
+
job_category: OpenSCAP Ansible Commands
|
4
|
+
description_format: Run scan for all OpenSCAP policies on given hosts
|
5
|
+
snippet: false
|
6
|
+
provider_type: Ansible
|
7
|
+
kind: job_template
|
8
|
+
model: JobTemplate
|
9
|
+
%>
|
10
|
+
|
11
|
+
<% raise "Create and assign a policy to this host before proceeding" if @host.policies_enc_raw.empty? -%>
|
12
|
+
---
|
13
|
+
- hosts: all
|
14
|
+
tasks:
|
15
|
+
<% @host.policies_enc_raw.each do |policy| -%>
|
16
|
+
- shell: /usr/bin/foreman_scap_client <%= policy['id'] %>
|
17
|
+
register: out
|
18
|
+
- debug: var=out
|
19
|
+
<% end -%>
|
20
|
+
|
data/config/routes.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
Rails.application.routes.draw do
|
4
|
+
match '/ansible/hostgroups' => 'react#index', :via => [:get]
|
5
|
+
match '/ansible/hostgroups/*page' => 'react#index', :via => [:get]
|
6
|
+
|
4
7
|
namespace :api, defaults: { format: 'json' } do
|
5
8
|
scope '(:apiv)',
|
6
9
|
:module => :v2,
|
@@ -4,7 +4,6 @@ require 'deface'
|
|
4
4
|
require 'acts_as_list'
|
5
5
|
require 'fast_gettext'
|
6
6
|
require 'gettext_i18n_rails'
|
7
|
-
require 'foreman_ansible_core' if Rails.env.test?
|
8
7
|
require 'foreman_ansible/remote_execution'
|
9
8
|
|
10
9
|
module ForemanAnsible
|
@@ -20,12 +19,6 @@ module ForemanAnsible
|
|
20
19
|
config.autoload_paths += Dir["#{config.root}/app/views"]
|
21
20
|
config.autoload_paths += Dir["#{config.root}/app/lib"]
|
22
21
|
|
23
|
-
initializer 'foreman_ansible.load_default_settings',
|
24
|
-
:before => :load_config_initializers do
|
25
|
-
require_dependency(File.join(ForemanAnsible::Engine.root,
|
26
|
-
'app/models/setting/ansible.rb'))
|
27
|
-
end
|
28
|
-
|
29
22
|
initializer 'foreman_ansible.register_gettext',
|
30
23
|
:after => :load_config_initializers do
|
31
24
|
locale_dir = File.join(File.expand_path('../..', __dir__), 'locale')
|
@@ -72,17 +65,6 @@ module ForemanAnsible
|
|
72
65
|
end
|
73
66
|
|
74
67
|
config.to_prepare do
|
75
|
-
foreman_version = ::Foreman::Version.new
|
76
|
-
if Rails.env.test? ||
|
77
|
-
foreman_version.major.to_i == 1 && foreman_version.minor.to_i < 13
|
78
|
-
::Foreman::Plugin.fact_importer_registry.register(:ansible, ForemanAnsible::FactImporter)
|
79
|
-
else
|
80
|
-
::Foreman::Plugin.fact_importer_registry.register(
|
81
|
-
:ansible,
|
82
|
-
ForemanAnsible::StructuredFactImporter
|
83
|
-
)
|
84
|
-
end
|
85
|
-
::FactParser.register_fact_parser(:ansible, ForemanAnsible::FactParser)
|
86
68
|
::Host::Managed.prepend ForemanAnsible::HostManagedExtensions
|
87
69
|
::Hostgroup.include ForemanAnsible::HostgroupExtensions
|
88
70
|
::HostsHelper.include ForemanAnsible::HostsHelperExtensions
|
@@ -1,7 +1,89 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
Foreman::Plugin.register :foreman_ansible do
|
4
|
-
requires_foreman '>=
|
4
|
+
requires_foreman '>= 3.0'
|
5
|
+
|
6
|
+
settings do
|
7
|
+
category :ansible, N_('Ansible') do
|
8
|
+
setting 'ansible_ssh_private_key_file',
|
9
|
+
type: :string,
|
10
|
+
description: N_('Use this to supply a path to an SSH Private Key '\
|
11
|
+
'that Ansible will use in lieu of a password '\
|
12
|
+
'Override with "ansible_ssh_private_key_file" '\
|
13
|
+
'host parameter'),
|
14
|
+
default: '',
|
15
|
+
full_name: N_('Private Key Path')
|
16
|
+
setting 'ansible_connection',
|
17
|
+
type: :string,
|
18
|
+
description: N_('Use this connection type by default when running '\
|
19
|
+
'Ansible playbooks. You can override this on hosts by '\
|
20
|
+
'adding a parameter "ansible_connection"'),
|
21
|
+
default: 'ssh',
|
22
|
+
full_name: N_('Connection type')
|
23
|
+
setting 'ansible_winrm_server_cert_validation',
|
24
|
+
type: :string,
|
25
|
+
description: N_('Enable/disable WinRM server certificate '\
|
26
|
+
'validation when running Ansible playbooks. You can override '\
|
27
|
+
'this on hosts by adding a parameter '\
|
28
|
+
'"ansible_winrm_server_cert_validation"'),
|
29
|
+
default: 'validate',
|
30
|
+
full_name: N_('WinRM cert Validation')
|
31
|
+
setting 'ansible_verbosity',
|
32
|
+
type: :integer,
|
33
|
+
description: N_('Foreman will add this level of verbosity for '\
|
34
|
+
'additional debugging output when running Ansible playbooks.'),
|
35
|
+
default: '0',
|
36
|
+
full_name: N_('Default verbosity level'),
|
37
|
+
value: nil,
|
38
|
+
collection: proc {
|
39
|
+
{ '0' => N_('Disabled'),
|
40
|
+
'1' => N_('Level 1 (-v)'),
|
41
|
+
'2' => N_('Level 2 (-vv)'),
|
42
|
+
'3' => N_('Level 3 (-vvv)'),
|
43
|
+
'4' => N_('Level 4 (-vvvv)') }
|
44
|
+
}
|
45
|
+
setting 'ansible_post_provision_timeout',
|
46
|
+
type: :integer,
|
47
|
+
description: N_('Timeout (in seconds) to set when Foreman will trigger a '\
|
48
|
+
'play Ansible roles task after a host is fully provisioned. '\
|
49
|
+
'Set this to the maximum time you expect a host to take '\
|
50
|
+
'until it is ready after a reboot.'),
|
51
|
+
default: '360',
|
52
|
+
full_name: N_('Post-provision timeout')
|
53
|
+
setting 'ansible_interval',
|
54
|
+
type: :integer,
|
55
|
+
description: N_('Timeout (in minutes) when hosts should have reported.'),
|
56
|
+
default: '30',
|
57
|
+
full_name: N_('Ansible report timeout')
|
58
|
+
setting 'ansible_out_of_sync_disabled',
|
59
|
+
type: :boolean,
|
60
|
+
description: format(N_('Disable host configuration status turning to out of'\
|
61
|
+
' sync for %{cfgmgmt} after report does not arrive within'\
|
62
|
+
' configured interval'), :cfgmgmt => 'Ansible'),
|
63
|
+
default: false,
|
64
|
+
full_name: format(N_('%{cfgmgmt} out of sync disabled'), :cfgmgmt => 'Ansible')
|
65
|
+
setting 'ansible_inventory_template',
|
66
|
+
type: :string,
|
67
|
+
description: N_('Foreman will use this template to schedule the report '\
|
68
|
+
'with Ansible inventory'),
|
69
|
+
default: 'Ansible - Ansible Inventory',
|
70
|
+
full_name: N_('Default Ansible inventory report template')
|
71
|
+
setting 'ansible_roles_to_ignore',
|
72
|
+
type: :array,
|
73
|
+
description: N_('Those roles will be excluded when importing roles from smart proxy, '\
|
74
|
+
'The expected input is comma separated values and you can use * wildcard metacharacters'\
|
75
|
+
'For example: foo*, *b*,*bar'),
|
76
|
+
default: [],
|
77
|
+
full_name: N_('Ansible roles to ignore')
|
78
|
+
setting 'foreman_ansible_proxy_batch_size',
|
79
|
+
type: :integer,
|
80
|
+
description: N_('Number of tasks which should be sent to the smart proxy in one request, '\
|
81
|
+
'if foreman_tasks_proxy_batch_trigger is enabled. '\
|
82
|
+
'If set, overrides foreman_tasks_proxy_batch_size setting for Ansible jobs.'),
|
83
|
+
default: nil,
|
84
|
+
full_name: N_('Proxy tasks batch size for Ansible')
|
85
|
+
end
|
86
|
+
end
|
5
87
|
|
6
88
|
security_block :foreman_ansible do
|
7
89
|
permission :play_roles_on_host,
|
@@ -29,23 +111,27 @@ Foreman::Plugin.register :foreman_ansible do
|
|
29
111
|
:resource_type => 'AnsibleRole'
|
30
112
|
permission :view_ansible_variables,
|
31
113
|
{
|
114
|
+
:lookup_values => [:index],
|
32
115
|
:ansible_variables => [:index, :auto_complete_search],
|
33
116
|
:'api/v2/ansible_variables' => [:index, :show]
|
34
117
|
},
|
35
118
|
:resource_type => 'AnsibleVariable'
|
36
119
|
permission :edit_ansible_variables,
|
37
|
-
{ :
|
120
|
+
{ :lookup_values => [:update],
|
121
|
+
:ansible_variables => [:edit, :update],
|
38
122
|
:'api/v2/ansible_variables' => [:update],
|
39
123
|
:'api/v2/ansible_override_values' => [:create, :destroy] },
|
40
124
|
:resource_type => 'AnsibleVariable'
|
41
125
|
permission :destroy_ansible_variables,
|
42
126
|
{
|
127
|
+
:lookup_values => [:destroy],
|
43
128
|
:ansible_variables => [:destroy],
|
44
129
|
:'api/v2/ansible_variables' => [:destroy, :obsolete]
|
45
130
|
},
|
46
131
|
:resource_type => 'AnsibleVariable'
|
47
132
|
permission :create_ansible_variables,
|
48
133
|
{
|
134
|
+
:lookup_values => [:create],
|
49
135
|
:ansible_variables => [:new, :create],
|
50
136
|
:'api/v2/ansible_variables' => [:create]
|
51
137
|
},
|
@@ -97,6 +183,32 @@ Foreman::Plugin.register :foreman_ansible do
|
|
97
183
|
parameter_filter Host::Managed, base_role_assignment_params.merge(:host_ansible_roles_attributes => {})
|
98
184
|
parameter_filter Hostgroup, base_role_assignment_params.merge(:hostgroup_ansible_roles_attributes => {})
|
99
185
|
|
186
|
+
register_global_js_file 'global'
|
187
|
+
|
188
|
+
extend_graphql_type :type => ::Types::Host do
|
189
|
+
field :all_ansible_roles, ::Types::InheritedAnsibleRole.connection_type, :null => true, :method => :present_all_ansible_roles
|
190
|
+
field :own_ansible_roles, ::Types::AnsibleRole.connection_type, :null => true
|
191
|
+
field :available_ansible_roles, ::Types::AnsibleRole.connection_type, :null => true
|
192
|
+
field :ansible_variables_with_overrides, Types::OverridenAnsibleVariable.connection_type, :null => false
|
193
|
+
|
194
|
+
def present_all_ansible_roles
|
195
|
+
inherited_ansible_roles = object.inherited_ansible_roles.map { |role| ::Presenters::AnsibleRolePresenter.new(role, true) }
|
196
|
+
ansible_roles = object.ansible_roles.map { |role| ::Presenters::AnsibleRolePresenter.new(role, false) }
|
197
|
+
(inherited_ansible_roles + ansible_roles).uniq
|
198
|
+
end
|
199
|
+
|
200
|
+
def ansible_variables_with_overrides
|
201
|
+
resolver = ::ForemanAnsible::OverrideResolver.new(object)
|
202
|
+
AnsibleVariable.where(:ansible_role_id => object.all_ansible_roles.pluck(:id), :override => true).map { |variable| ::Presenters::OverridenAnsibleVariablePresenter.new variable, resolver }
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
register_graphql_query_field :ansible_roles, '::Types::AnsibleRole', :collection_field
|
207
|
+
register_graphql_mutation_field :assign_ansible_roles, '::Mutations::Hosts::AssignAnsibleRoles'
|
208
|
+
register_graphql_mutation_field :delete_ansible_variable_override, ::Mutations::AnsibleVariableOverrides::Delete
|
209
|
+
register_graphql_mutation_field :update_ansible_variable_override, ::Mutations::AnsibleVariableOverrides::Update
|
210
|
+
register_graphql_mutation_field :create_ansible_variable_override, ::Mutations::AnsibleVariableOverrides::Create
|
211
|
+
|
100
212
|
divider :top_menu, :caption => N_('Ansible'), :parent => :configure_menu
|
101
213
|
menu :top_menu, :ansible_roles,
|
102
214
|
:caption => N_('Roles'),
|
data/package.json
CHANGED
@@ -7,23 +7,27 @@
|
|
7
7
|
"test": "test"
|
8
8
|
},
|
9
9
|
"peerDependencies": {
|
10
|
-
"@theforeman/vendor": ">=
|
10
|
+
"@theforeman/vendor": ">= 8.16.0"
|
11
11
|
},
|
12
12
|
"dependencies": {
|
13
13
|
"react-json-tree": "^0.11.0"
|
14
14
|
},
|
15
15
|
"devDependencies": {
|
16
16
|
"@babel/core": "^7.7.0",
|
17
|
-
"@
|
18
|
-
"@theforeman/
|
19
|
-
"@theforeman/
|
20
|
-
"@theforeman/
|
17
|
+
"@testing-library/user-event": "^13.2.1",
|
18
|
+
"@theforeman/builder": "^8.4.1",
|
19
|
+
"@theforeman/eslint-plugin-foreman": "^8.4.1",
|
20
|
+
"@theforeman/find-foreman": "^8.4.1",
|
21
|
+
"@theforeman/stories": "^8.4.1",
|
22
|
+
"@theforeman/test": "^8.9.0",
|
23
|
+
"@theforeman/vendor-dev": "^8.4.1",
|
24
|
+
"@testing-library/user-event": "^13.2.1",
|
21
25
|
"babel-eslint": "^10.0.3",
|
22
26
|
"eslint": "^6.7.2",
|
23
27
|
"prettier": "^1.13.5"
|
24
28
|
},
|
25
29
|
"scripts": {
|
26
|
-
"test": "tfm-test --plugin",
|
30
|
+
"test": "tfm-test --plugin --config jest.config.js",
|
27
31
|
"lint": "tfm-lint --plugin -d webpack"
|
28
32
|
},
|
29
33
|
"repository": {
|
@@ -34,8 +34,7 @@ module Api
|
|
34
34
|
|
35
35
|
test 'schedule inventory by user' do
|
36
36
|
report = FactoryBot.create(:report_template)
|
37
|
-
Setting
|
38
|
-
:default => report.name, :description => 'inventory'
|
37
|
+
Setting['ansible_inventory_template'] = report.name
|
39
38
|
user = FactoryBot.create(:user)
|
40
39
|
user.roles << Role.find_by(:name => 'Ansible Tower Inventory Reader')
|
41
40
|
post :schedule, { :session => set_session_user(user) }
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
module Mutations
|
4
|
+
module Hosts
|
5
|
+
class CreateMutationTest < GraphQLQueryTestCase
|
6
|
+
let(:tax_location) { FactoryBot.create(:location) }
|
7
|
+
let(:location_id) { Foreman::GlobalId.for(tax_location) }
|
8
|
+
let(:organization) { FactoryBot.create(:organization) }
|
9
|
+
let(:organization_id) { Foreman::GlobalId.for(organization) }
|
10
|
+
|
11
|
+
let(:role1) { FactoryBot.create(:ansible_role) }
|
12
|
+
let(:role2) { FactoryBot.create(:ansible_role) }
|
13
|
+
let(:role3) { FactoryBot.create(:ansible_role) }
|
14
|
+
let(:host) { FactoryBot.create(:host, :ansible_roles => [role1, role2, role3], :organization => organization, :location => tax_location) }
|
15
|
+
|
16
|
+
let(:variables) { { id: Foreman::GlobalId.for(host), ansibleRoleIds: [role3.id, role2.id, role1.id] } }
|
17
|
+
let(:query) do
|
18
|
+
<<-GRAPHQL
|
19
|
+
mutation AssignAnsibleRoles($id: ID!, $ansibleRoleIds: [Int!]!) {
|
20
|
+
assignAnsibleRoles(input: { id: $id, ansibleRoleIds: $ansibleRoleIds }) {
|
21
|
+
host {
|
22
|
+
id
|
23
|
+
ownAnsibleRoles {
|
24
|
+
nodes {
|
25
|
+
id
|
26
|
+
name
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
errors {
|
31
|
+
path
|
32
|
+
message
|
33
|
+
}
|
34
|
+
}
|
35
|
+
}
|
36
|
+
GRAPHQL
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'with admin permissions' do
|
40
|
+
let(:context_user) { FactoryBot.create(:user, :admin) }
|
41
|
+
let(:data) { result['data']['assignAnsibleRoles']['host'] }
|
42
|
+
|
43
|
+
it 'reorderes ansible roles' do
|
44
|
+
assert_empty result['errors']
|
45
|
+
assert_not_nil data
|
46
|
+
assert_empty result['data']['assignAnsibleRoles']['errors']
|
47
|
+
|
48
|
+
assert_equal([role3, role2, role1].map { |role| Foreman::GlobalId.for role }, data['ownAnsibleRoles']['nodes'].map { |node| node['id'] })
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'with edit permission' do
|
53
|
+
let(:context_user) do
|
54
|
+
setup_user('edit', 'hosts') do |user|
|
55
|
+
user.roles << Role.find_by(name: 'Viewer')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
let(:data) { result['data']['assignAnsibleRoles']['host'] }
|
59
|
+
let(:variables) { { id: Foreman::GlobalId.for(host), ansibleRoleIds: [role3.id, role2.id] } }
|
60
|
+
|
61
|
+
before do
|
62
|
+
Location.current = tax_location
|
63
|
+
Organization.current = organization
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'reorderes ansible roles' do
|
67
|
+
assert_empty result['errors']
|
68
|
+
assert_not_nil data
|
69
|
+
assert_empty result['data']['assignAnsibleRoles']['errors']
|
70
|
+
|
71
|
+
assert_equal([role3, role2].map { |role| Foreman::GlobalId.for role }, data['ownAnsibleRoles']['nodes'].map { |node| node['id'] })
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'with view only permissions' do
|
76
|
+
let(:context_user) do
|
77
|
+
setup_user('show', 'hosts') do |user|
|
78
|
+
user.roles << Role.find_by(name: 'Viewer')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
before do
|
83
|
+
Location.current = tax_location
|
84
|
+
Organization.current = organization
|
85
|
+
end
|
86
|
+
|
87
|
+
test 'cannot create a host' do
|
88
|
+
expected_error = 'Unauthorized. You do not have the required permission edit_hosts.'
|
89
|
+
|
90
|
+
assert_not_empty result['errors']
|
91
|
+
assert_includes result['errors'].map { |e| e['message'] }, expected_error
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
module Queries
|
4
|
+
class AnsibleRolesQueryTest < GraphQLQueryTestCase
|
5
|
+
let(:query) do
|
6
|
+
<<-GRAPHQL
|
7
|
+
query {
|
8
|
+
ansibleRoles {
|
9
|
+
totalCount
|
10
|
+
nodes {
|
11
|
+
id
|
12
|
+
name
|
13
|
+
}
|
14
|
+
}
|
15
|
+
}
|
16
|
+
GRAPHQL
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:data) { result['data']['ansibleRoles'] }
|
20
|
+
|
21
|
+
setup do
|
22
|
+
FactoryBot.create_list(:ansible_role, 2)
|
23
|
+
end
|
24
|
+
|
25
|
+
test 'should fetch Ansible roles' do
|
26
|
+
assert_empty result['errors']
|
27
|
+
|
28
|
+
expected_count = AnsibleRole.count
|
29
|
+
|
30
|
+
assert_not_equal 0, expected_count
|
31
|
+
assert_equal expected_count, data['totalCount']
|
32
|
+
assert_equal expected_count, data['nodes'].count
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -30,14 +30,11 @@ class AnsibleProviderTest < ActiveSupport::TestCase
|
|
30
30
|
end
|
31
31
|
|
32
32
|
context 'when using secrets' do
|
33
|
-
let(:host) { FactoryBot.
|
33
|
+
let(:host) { FactoryBot.create(:host) }
|
34
34
|
|
35
35
|
it 'generates secrets properly' do
|
36
|
-
|
37
|
-
|
38
|
-
'remote_execution_effective_user_password' => 'letmein'
|
39
|
-
}
|
40
|
-
host.expects(:params).twice.returns(params)
|
36
|
+
host.parameters << HostParameter.new(name: 'remote_execution_ssh_password', value: 'password')
|
37
|
+
host.parameters << HostParameter.new(name: 'remote_execution_effective_user_password', value: 'letmein')
|
41
38
|
secrets = ForemanAnsible::AnsibleProvider.secrets(host)
|
42
39
|
host_secrets = secrets['per-host'][host.name]
|
43
40
|
assert_equal host_secrets['ansible_password'], 'password'
|
@@ -62,4 +62,12 @@ class HostManagedExtensionsTest < ActiveSupport::TestCase
|
|
62
62
|
FactoryBot.create(:host_ansible_role, :ansible_role_id => @role1.id, :position => 0, :host_id => host.id)
|
63
63
|
host.all_ansible_roles.must_equal [@role2, @role1]
|
64
64
|
end
|
65
|
+
|
66
|
+
test 'should find hosts with role2' do
|
67
|
+
host1 = FactoryBot.create(:host, :ansible_roles => [@role2])
|
68
|
+
host2 = FactoryBot.create(:host, :hostgroup => @hostgroup)
|
69
|
+
result = Host::Managed.search_for("ansible_role= #{@role2.name}").pluck(:id)
|
70
|
+
assert_include result, host1.id
|
71
|
+
assert_include result, host2.id
|
72
|
+
end
|
65
73
|
end
|
@@ -55,4 +55,10 @@ class HostgroupExtensionsTest < ActiveSupport::TestCase
|
|
55
55
|
@hostgroup.parent = @hostgroup_parent
|
56
56
|
@hostgroup.inherited_and_own_ansible_roles.must_equal [@role2, @role1]
|
57
57
|
end
|
58
|
+
|
59
|
+
describe '#cloned_ansibe_roles' do
|
60
|
+
test 'clone ansible roles from hostgroup parent' do
|
61
|
+
@hostgroup_parent.clone.all_ansible_roles.must_equal @hostgroup_parent.all_ansible_roles
|
62
|
+
end
|
63
|
+
end
|
58
64
|
end
|
@@ -6,43 +6,17 @@ class AnsibleReportsHelperTest < ActiveSupport::TestCase
|
|
6
6
|
include ForemanAnsible::AnsibleReportsHelper
|
7
7
|
include ActionView::Helpers::TagHelper
|
8
8
|
|
9
|
-
test '
|
9
|
+
test 'module message extraction' do
|
10
10
|
log_value = <<-ANSIBLELOG.strip_heredoc
|
11
|
-
|
11
|
+
{"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": "package"}
|
12
12
|
ANSIBLELOG
|
13
13
|
message = FactoryBot.build(:message)
|
14
14
|
message.value = log_value
|
15
15
|
log = FactoryBot.build(:log)
|
16
16
|
log.message = message
|
17
17
|
assert_match(
|
18
|
-
/
|
19
|
-
|
20
|
-
)
|
21
|
-
end
|
22
|
-
|
23
|
-
test 'pretty print is able to print a hash' do
|
24
|
-
hash = {
|
25
|
-
'allow_downgrade' => false,
|
26
|
-
'name' => ['ntp'],
|
27
|
-
'list' => nil,
|
28
|
-
'disable_gpg_check' => false,
|
29
|
-
'conf_file' => nil,
|
30
|
-
'install_repoquery' => true,
|
31
|
-
'state' => 'installed',
|
32
|
-
'disablerepo' => nil,
|
33
|
-
'update_cache' => false,
|
34
|
-
'enablerepo' => nil,
|
35
|
-
'exclude' => nil,
|
36
|
-
'security' => false,
|
37
|
-
'validate_certs' => true,
|
38
|
-
'installroot' => '/',
|
39
|
-
'skip_broken' => false
|
40
|
-
}
|
41
|
-
assert_equal(
|
42
|
-
hash,
|
43
|
-
remove_keys(
|
44
|
-
hash
|
45
|
-
)
|
18
|
+
/Nothing to do/,
|
19
|
+
ansible_module_message(log).to_s
|
46
20
|
)
|
47
21
|
end
|
48
22
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_plugin_helper'
|
4
|
+
|
5
|
+
module ForemanAnsible
|
6
|
+
class OverrideResolverTest < ActiveSupport::TestCase
|
7
|
+
test 'should return no overrides when no roles assigned to host' do
|
8
|
+
assert_empty OverrideResolver.new(FactoryBot.build(:host)).overrides
|
9
|
+
end
|
10
|
+
|
11
|
+
test 'should return overrides for host' do
|
12
|
+
first_role = FactoryBot.create(:ansible_role)
|
13
|
+
first_var = FactoryBot.create(:ansible_variable, :override => true, :ansible_role => first_role)
|
14
|
+
second_role = FactoryBot.create(:ansible_role)
|
15
|
+
second_var = FactoryBot.create(:ansible_variable, :override => true, :ansible_role => second_role)
|
16
|
+
host = FactoryBot.create(:host, :ansible_roles => [first_role])
|
17
|
+
another_host = FactoryBot.create(:host)
|
18
|
+
|
19
|
+
FactoryBot.create(:lookup_value, :match => "fqdn=#{host.name}", :lookup_key_id => first_var.id)
|
20
|
+
FactoryBot.create(:lookup_value, :match => "fqdn=#{another_host.name}", :lookup_key_id => first_var.id)
|
21
|
+
FactoryBot.create(:lookup_value, :match => "fqdn=#{host.name}", :lookup_key_id => second_var.id)
|
22
|
+
|
23
|
+
assert_not_nil OverrideResolver.new(host).resolve(first_var)
|
24
|
+
assert_nil OverrideResolver.new(another_host).resolve(first_var)
|
25
|
+
assert_nil OverrideResolver.new(host).resolve(second_var)
|
26
|
+
end
|
27
|
+
|
28
|
+
test 'should raise when no host specified' do
|
29
|
+
assert_raises Foreman::Exception do
|
30
|
+
OverrideResolver.new(nil)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|