foreman_ansible 6.3.4 → 6.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/helpers/foreman_ansible/ansible_reports_helper.rb +35 -54
- data/app/helpers/foreman_ansible/ansible_roles_data_preparations.rb +22 -22
- data/app/models/concerns/foreman_ansible/hostgroup_extensions.rb +1 -1
- data/app/models/foreman_ansible/ansible_provider.rb +54 -2
- 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 +1 -1
- data/lib/foreman_ansible/engine.rb +0 -1
- data/lib/foreman_ansible/register.rb +4 -3
- data/lib/foreman_ansible/version.rb +1 -1
- data/package.json +7 -5
- data/test/unit/ansible_provider_test.rb +6 -3
- data/test/unit/helpers/ansible_reports_helper_test.rb +4 -30
- data/test/unit/hostgroup_ansible_role_test.rb +0 -13
- data/webpack/components/AnsibleHostDetail/AnsibleHostDetail.js +35 -0
- data/webpack/components/AnsibleHostDetail/AnsibleHostDetail.scss +6 -0
- data/webpack/components/AnsibleHostDetail/AnsibleHostDetail.test.js +14 -0
- data/webpack/components/AnsibleHostDetail/index.js +6 -0
- data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AnsiblePermissionDenied.test.js.snap +2 -0
- data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AssignedRolesList.test.js.snap +4 -4
- data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AvailableRolesList.test.js.snap +5 -0
- data/webpack/global_index.js +12 -0
- metadata +14 -35
- 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/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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 05c975cb77fe5add41b7281dfa1c2451bb22a09ab5dc6251ab06fd4d00b834e2
|
4
|
+
data.tar.gz: 86613f4be767b5af80a06f83b9e13f8f030cd80bc362d866323111b61a0b23a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc27695cef374e8b709ddc3c3882056587cbf975ac7d497c1fec5aaa1885f85bcb3677c2c7fd3f2602f529cba0a6736017703f6d7ca413eb5f2ed7a6de112a94
|
7
|
+
data.tar.gz: ba0c5f9b94a51b7328cc0df73bfcc0f47831b1004b275be935fa73a83ae9c6f12b81086071ebe69292c8aa5ad436c5389a6a6f1ac457720bcefe034b456c0ec8
|
@@ -4,21 +4,19 @@ module ForemanAnsible
|
|
4
4
|
# This module takes the config reports stored in Foreman for Ansible and
|
5
5
|
# modifies them to be properly presented in views
|
6
6
|
module AnsibleReportsHelper
|
7
|
-
ANSIBLE_META_KEYS = %w[
|
8
|
-
_ansible_parsed _ansible_no_log _ansible_item_result
|
9
|
-
_ansible_ignore_errors _ansible_verbose_always _ansible_verbose_override
|
10
|
-
].freeze
|
11
|
-
ANSIBLE_HIDDEN_KEYS = %w[
|
12
|
-
invocation module_args results ansible_facts
|
13
|
-
stdout stderr
|
14
|
-
].freeze
|
15
|
-
|
16
7
|
def ansible_module_name(log)
|
17
8
|
source_value = log.source&.value
|
18
9
|
name = source_value.split(':')[0].strip if source_value&.include?(':')
|
19
10
|
name
|
20
11
|
end
|
21
12
|
|
13
|
+
def ansible_task_name(log)
|
14
|
+
source_value = log.source&.value
|
15
|
+
return source_value || no_data_message unless source_value.include? ':'
|
16
|
+
name = source_value.split(':')[1].strip if source_value.include?(':')
|
17
|
+
name || no_data_message
|
18
|
+
end
|
19
|
+
|
22
20
|
def ansible_run_in_check_mode?(log)
|
23
21
|
log.message&.value == 'check_mode_enabled' if check_mode_log?(log)
|
24
22
|
end
|
@@ -27,12 +25,36 @@ module ForemanAnsible
|
|
27
25
|
log.source&.value == 'check_mode'
|
28
26
|
end
|
29
27
|
|
30
|
-
def
|
31
|
-
|
28
|
+
def ansible_module_message(log)
|
29
|
+
msg_json = parsed_message_json(log)
|
30
|
+
module_action = msg_json['module']
|
31
|
+
case module_action
|
32
|
+
when 'package'
|
33
|
+
msg_json['results'].empty? ? msg_json['msg'] : msg_json['results']
|
34
|
+
when 'template'
|
35
|
+
module_args = msg_json['invocation']['module_args']
|
36
|
+
_("Rendered template #{module_args['_original_basename']} to #{msg_json['dest']}")
|
37
|
+
when 'service'
|
38
|
+
_("Service #{msg_json['name']} #{msg_json['state']} (enabled: #{msg_json['enabled']})")
|
39
|
+
when 'group'
|
40
|
+
_("User group #{msg_json['name']} #{msg_json['state']}, gid: #{msg_json['gid']}")
|
41
|
+
when 'user'
|
42
|
+
_("User #{msg_json['name']} #{msg_json['state']}, uid: #{msg_json['uid']}")
|
43
|
+
when 'cron'
|
44
|
+
module_args = msg_json['invocation']['module_args']
|
45
|
+
_("Cron job: #{module_args['minute']} #{module_args['hour']} #{module_args['day']} #{module_args['month']} #{module_args['weekday']} #{module_args['job']} (disabled: #{module_args['disabled']})")
|
46
|
+
when 'copy'
|
47
|
+
module_args = msg_json['invocation']['module_args']
|
48
|
+
_("Copy #{module_args['_original_basename']} to #{msg_json['dest']}")
|
49
|
+
when 'command', 'shell'
|
50
|
+
msg_json['stdout_lines']
|
51
|
+
else
|
52
|
+
no_data_message
|
53
|
+
end
|
32
54
|
end
|
33
55
|
|
34
|
-
def
|
35
|
-
|
56
|
+
def no_data_message
|
57
|
+
_('No additional data')
|
36
58
|
end
|
37
59
|
|
38
60
|
def ansible_report_origin_icon
|
@@ -49,49 +71,8 @@ module ForemanAnsible
|
|
49
71
|
false
|
50
72
|
end
|
51
73
|
|
52
|
-
def report_json_viewer(json)
|
53
|
-
react_component('ReportJsonViewer', data: json)
|
54
|
-
end
|
55
|
-
|
56
74
|
private
|
57
75
|
|
58
|
-
def module_invocations(hash)
|
59
|
-
invocations = []
|
60
|
-
invocations << hash.delete('invocation')
|
61
|
-
results = hash.delete('results')
|
62
|
-
invocations << results
|
63
|
-
invocations = invocations.compact.flatten.map do |ih|
|
64
|
-
ih.is_a?(Hash) ? remove_keys(ih) : ih
|
65
|
-
end
|
66
|
-
invocations
|
67
|
-
end
|
68
|
-
|
69
|
-
def pretty_print_hash(hash)
|
70
|
-
prettyp = JSON.pretty_generate(remove_keys(hash))
|
71
|
-
prettyp.gsub!(/{\n*/, "\n")
|
72
|
-
prettyp.gsub!(/},*\n*/, "\n")
|
73
|
-
prettyp.gsub!(/^(\[|\])/, '')
|
74
|
-
prettyp.gsub!(/^[\s]*$\n/, '')
|
75
|
-
paragraph_style = 'white-space:pre;padding: 2em 0'
|
76
|
-
tag(:p, prettyp, :style => paragraph_style)
|
77
|
-
end
|
78
|
-
|
79
|
-
def hash_with_keys_removed(hash)
|
80
|
-
new_hash = remove_keys(hash)
|
81
|
-
remove_keys(new_hash, ANSIBLE_HIDDEN_KEYS)
|
82
|
-
end
|
83
|
-
|
84
|
-
def remove_keys(hash, keys = ANSIBLE_META_KEYS)
|
85
|
-
hash.each do |key, value|
|
86
|
-
if value.is_a? Array
|
87
|
-
value.each { |h| remove_keys(h) if h.is_a? Hash }
|
88
|
-
elsif value.is_a? Hash
|
89
|
-
remove_keys(value)
|
90
|
-
end
|
91
|
-
hash.delete(key) if keys.include? key
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
76
|
def parsed_message_json(log)
|
96
77
|
JSON.parse(log.message.value)
|
97
78
|
rescue StandardError => e
|
@@ -2,22 +2,22 @@
|
|
2
2
|
|
3
3
|
module ForemanAnsible
|
4
4
|
module AnsibleRolesDataPreparations
|
5
|
-
VARIABLE_ACTION_NAMES = { 'new' =>
|
6
|
-
ROLE_ACTION_NAMES = { 'new' =>
|
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
7
|
|
8
|
-
def
|
9
|
-
VARIABLE_ACTION_NAMES[kind]
|
8
|
+
def get_variable_action(kind)
|
9
|
+
_(VARIABLE_ACTION_NAMES[kind])
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
ROLE_ACTION_NAMES[kind]
|
12
|
+
def get_role_action(kind)
|
13
|
+
_(ROLE_ACTION_NAMES[kind])
|
14
14
|
end
|
15
15
|
|
16
16
|
def get_old_roles_variables(imported_variables, role)
|
17
|
-
variables = { '
|
17
|
+
variables = { 'Add' => [], 'Remove' => [], 'Update' => [] }
|
18
18
|
imported_variables.each do |kind, temp_variables|
|
19
19
|
temp_variables.each do |temp_variable|
|
20
|
-
variables[kind].append(temp_variable.key) if temp_variable.ansible_role_id == role.id
|
20
|
+
variables[get_variable_action(kind)].append(temp_variable.key) if temp_variable.ansible_role_id == role.id
|
21
21
|
end
|
22
22
|
end
|
23
23
|
variables
|
@@ -26,16 +26,16 @@ module ForemanAnsible
|
|
26
26
|
def variables_to_s(variables)
|
27
27
|
str = ''
|
28
28
|
variables.each do |action, temp_variables|
|
29
|
-
str += "#{
|
29
|
+
str += "#{action}: #{temp_variables.size}, " unless temp_variables.empty?
|
30
30
|
end
|
31
31
|
str[0..-3]
|
32
32
|
end
|
33
33
|
|
34
34
|
def get_roles_variables(imported_variables, variables_importer, kind, role)
|
35
35
|
if kind == 'new'
|
36
|
-
variables = { '
|
36
|
+
variables = { 'Add' => variables_importer.get_variables_names(role.name) }
|
37
37
|
elsif kind == 'obsolete'
|
38
|
-
variables = { '
|
38
|
+
variables = { 'Remove' => role.ansible_variables.map(&:key) }
|
39
39
|
elsif kind == 'old'
|
40
40
|
variables = get_old_roles_variables(imported_variables, role)
|
41
41
|
end
|
@@ -51,25 +51,24 @@ module ForemanAnsible
|
|
51
51
|
match.to_s.empty? ? nil : match
|
52
52
|
end
|
53
53
|
|
54
|
-
def prepare_api_row(role, kind, variables)
|
54
|
+
def prepare_api_row(role, kind, variables, role_action)
|
55
55
|
{
|
56
56
|
name: role.name,
|
57
57
|
id: role.id,
|
58
|
-
role_action:
|
58
|
+
role_action: role_action,
|
59
59
|
variables: variables,
|
60
|
-
hosts_count:
|
61
|
-
hostgroup_count:
|
60
|
+
hosts_count: role_action == 'Remove Role' ? role.hosts.count : '',
|
61
|
+
hostgroup_count: role_action == 'Remove Role' ? role.hostgroups.count : '',
|
62
62
|
kind: kind
|
63
63
|
}
|
64
64
|
end
|
65
65
|
|
66
|
-
def prepare_ui_row(role, kind, variables)
|
66
|
+
def prepare_ui_row(role, kind, variables, role_action)
|
67
67
|
{ cells: [
|
68
68
|
role.name,
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
kind == 'obsolete' ? role.hostgroups.count : ''
|
69
|
+
role_action, variables,
|
70
|
+
role_action == 'Remove Role' ? role.hosts.count : '',
|
71
|
+
role_action == 'Remove Role' ? role.hostgroups.count : ''
|
73
72
|
],
|
74
73
|
role: role, kind: kind, id: role.name }
|
75
74
|
end
|
@@ -82,10 +81,11 @@ module ForemanAnsible
|
|
82
81
|
next if role_match_excluded_roles(role.name)
|
83
82
|
variables = get_roles_variables(imported_variables, variables_importer, kind, role)
|
84
83
|
next if variables.empty? && kind['old']
|
84
|
+
role_action = get_role_action(kind)
|
85
85
|
if is_ui
|
86
|
-
rows.append(prepare_ui_row(role, kind, variables))
|
86
|
+
rows.append(prepare_ui_row(role, kind, variables, role_action))
|
87
87
|
else
|
88
|
-
rows.append(prepare_api_row(role, kind, variables))
|
88
|
+
rows.append(prepare_api_row(role, kind, variables, role_action))
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
@@ -6,7 +6,7 @@ module ForemanAnsible
|
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
included do
|
9
|
-
has_many :hostgroup_ansible_roles,
|
9
|
+
has_many :hostgroup_ansible_roles, :foreign_key => :hostgroup_id
|
10
10
|
has_many :ansible_roles,
|
11
11
|
-> { order('hostgroup_ansible_roles.position ASC') },
|
12
12
|
:through => :hostgroup_ansible_roles,
|
@@ -18,6 +18,10 @@ if defined? ForemanRemoteExecution
|
|
18
18
|
'Ansible'
|
19
19
|
end
|
20
20
|
|
21
|
+
def provider_input_namespace
|
22
|
+
:ansible
|
23
|
+
end
|
24
|
+
|
21
25
|
def proxy_command_options(template_invocation, host)
|
22
26
|
super(template_invocation, host).merge(
|
23
27
|
'ansible_inventory' => ::ForemanAnsible::InventoryCreator.new(
|
@@ -34,7 +38,6 @@ if defined? ForemanRemoteExecution
|
|
34
38
|
|
35
39
|
def secrets(host)
|
36
40
|
{
|
37
|
-
:key_passphrase => Setting[:remote_execution_ssh_key_passphrase],
|
38
41
|
'per-host' => {
|
39
42
|
host.name => {
|
40
43
|
'ansible_password' => rex_ssh_password(host),
|
@@ -52,16 +55,65 @@ if defined? ForemanRemoteExecution
|
|
52
55
|
host_setting(host, 'remote_execution_effective_user_password')
|
53
56
|
end
|
54
57
|
|
58
|
+
def host_setting(host, setting)
|
59
|
+
host.params[setting.to_s] || Setting[setting]
|
60
|
+
end
|
61
|
+
|
55
62
|
def supports_effective_user?
|
56
63
|
true
|
57
64
|
end
|
58
65
|
|
66
|
+
def provider_inputs
|
67
|
+
[
|
68
|
+
ForemanRemoteExecution::ProviderInput.new(
|
69
|
+
name: 'tags',
|
70
|
+
label: _('Tags'),
|
71
|
+
value: '',
|
72
|
+
value_type: 'plain',
|
73
|
+
description: 'Tags used for Ansible execution'
|
74
|
+
),
|
75
|
+
ForemanRemoteExecution::ProviderInput.new(
|
76
|
+
name: 'tags_flag',
|
77
|
+
label: _('Include/Exclude Tags'),
|
78
|
+
value: 'include',
|
79
|
+
description: 'Option whether to include or exclude tags',
|
80
|
+
options: "include\nexclude"
|
81
|
+
)
|
82
|
+
]
|
83
|
+
end
|
84
|
+
|
85
|
+
def provider_inputs_doc
|
86
|
+
opts = provider_inputs.find { |input| input.name == 'tags_flag' }.options.split("\n")
|
87
|
+
{
|
88
|
+
:namespace => provider_input_namespace,
|
89
|
+
:opts => { :desc => N_('Ansible provider specific inputs') },
|
90
|
+
:children => [
|
91
|
+
{
|
92
|
+
:name => :tags,
|
93
|
+
:type => Array,
|
94
|
+
:opts => { :required => false, :desc => N_('A comma separated list of tags to use for Ansible run') }
|
95
|
+
},
|
96
|
+
{
|
97
|
+
:name => :tags_flag,
|
98
|
+
:type => opts,
|
99
|
+
:opts => { :required => false, :desc => N_('Include\Exclude tags for Ansible run') }
|
100
|
+
}
|
101
|
+
]
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
def proxy_command_provider_inputs(template_invocation)
|
106
|
+
tags = template_invocation.provider_input_values.find_by(:name => 'tags')&.value || ''
|
107
|
+
tags_flag = template_invocation.provider_input_values.find_by(:name => 'tags_flag')&.value || ''
|
108
|
+
{ :tags => tags, :tags_flag => tags_flag }
|
109
|
+
end
|
110
|
+
|
59
111
|
def proxy_operation_name
|
60
112
|
'ansible-runner'
|
61
113
|
end
|
62
114
|
|
63
115
|
def proxy_action_class
|
64
|
-
'
|
116
|
+
'Proxy::Ansible::TaskLauncher::Playbook::PlaybookRunnerAction'
|
65
117
|
end
|
66
118
|
|
67
119
|
private
|
@@ -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
|
@@ -34,7 +34,7 @@ kind: job_template
|
|
34
34
|
url: <%= subscription_manager_configuration_url(@host) %>
|
35
35
|
dest: /usr/share/convert2rhel/subscription-manager/katello-ca-consumer-latest.noarch.rpm
|
36
36
|
- name: Start convert2rhel
|
37
|
-
command: convert2rhel -y --activationkey "<%= input('Activation Key') %>" --org "<%= @host.organization.label %>"
|
37
|
+
command: convert2rhel -y --activationkey "<%= input('Activation Key') %>" --org "<%= @host.organization.label %>" > /root/convert2rhel.log
|
38
38
|
<%- if input('Restart') == "yes" -%>
|
39
39
|
- name: Reboot the machine
|
40
40
|
reboot:
|
@@ -76,10 +76,9 @@ Foreman::Plugin.register :foreman_ansible do
|
|
76
76
|
|
77
77
|
role 'Ansible Roles Manager',
|
78
78
|
[:play_roles_on_host, :play_roles_on_hostgroup,
|
79
|
-
:create_job_invocations, :view_job_templates, # to allow the play_roles
|
80
|
-
:create_template_invocations, :view_smart_proxies, # ...
|
81
79
|
:view_ansible_roles, :destroy_ansible_roles,
|
82
|
-
:import_ansible_roles,
|
80
|
+
:import_ansible_roles,
|
81
|
+
:view_ansible_variables,
|
83
82
|
:create_ansible_variables, :import_ansible_variables,
|
84
83
|
:edit_ansible_variables, :destroy_ansible_variables]
|
85
84
|
|
@@ -97,6 +96,8 @@ Foreman::Plugin.register :foreman_ansible do
|
|
97
96
|
parameter_filter Host::Managed, base_role_assignment_params.merge(:host_ansible_roles_attributes => {})
|
98
97
|
parameter_filter Hostgroup, base_role_assignment_params.merge(:hostgroup_ansible_roles_attributes => {})
|
99
98
|
|
99
|
+
register_global_js_file 'global'
|
100
|
+
|
100
101
|
divider :top_menu, :caption => N_('Ansible'), :parent => :configure_menu
|
101
102
|
menu :top_menu, :ansible_roles,
|
102
103
|
:caption => N_('Roles'),
|
data/package.json
CHANGED
@@ -14,16 +14,18 @@
|
|
14
14
|
},
|
15
15
|
"devDependencies": {
|
16
16
|
"@babel/core": "^7.7.0",
|
17
|
-
"@theforeman/builder": "^
|
18
|
-
"@theforeman/eslint-plugin-foreman": "
|
19
|
-
"@theforeman/
|
20
|
-
"@theforeman/
|
17
|
+
"@theforeman/builder": "^8.4.1",
|
18
|
+
"@theforeman/eslint-plugin-foreman": "^8.4.1",
|
19
|
+
"@theforeman/find-foreman": "^8.4.1",
|
20
|
+
"@theforeman/stories": "^8.4.1",
|
21
|
+
"@theforeman/test": "^8.4.1",
|
22
|
+
"@theforeman/vendor-dev": "^8.4.1",
|
21
23
|
"babel-eslint": "^10.0.3",
|
22
24
|
"eslint": "^6.7.2",
|
23
25
|
"prettier": "^1.13.5"
|
24
26
|
},
|
25
27
|
"scripts": {
|
26
|
-
"test": "tfm-test --plugin",
|
28
|
+
"test": "tfm-test --plugin --config jest.config.js",
|
27
29
|
"lint": "tfm-lint --plugin -d webpack"
|
28
30
|
},
|
29
31
|
"repository": {
|
@@ -30,11 +30,14 @@ class AnsibleProviderTest < ActiveSupport::TestCase
|
|
30
30
|
end
|
31
31
|
|
32
32
|
context 'when using secrets' do
|
33
|
-
let(:host) { FactoryBot.
|
33
|
+
let(:host) { FactoryBot.build(:host) }
|
34
34
|
|
35
35
|
it 'generates secrets properly' do
|
36
|
-
|
37
|
-
|
36
|
+
params = {
|
37
|
+
'remote_execution_ssh_password' => 'password',
|
38
|
+
'remote_execution_effective_user_password' => 'letmein'
|
39
|
+
}
|
40
|
+
host.expects(:params).twice.returns(params)
|
38
41
|
secrets = ForemanAnsible::AnsibleProvider.secrets(host)
|
39
42
|
host_secrets = secrets['per-host'][host.name]
|
40
43
|
assert_equal host_secrets['ansible_password'], 'password'
|
@@ -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
|
@@ -19,17 +19,4 @@ class HostgroupAnsibleRoleTest < ActiveSupport::TestCase
|
|
19
19
|
end
|
20
20
|
should validate_uniqueness_of(:ansible_role_id).scoped_to(:hostgroup_id)
|
21
21
|
end
|
22
|
-
|
23
|
-
describe 'ordering' do
|
24
|
-
test 'should list roles in correct order' do
|
25
|
-
hg = FactoryBot.create(:hostgroup)
|
26
|
-
5.times do |idx|
|
27
|
-
HostgroupAnsibleRole.create(:hostgroup => hg, :ansible_role => FactoryBot.create(:ansible_role), :position => idx)
|
28
|
-
end
|
29
|
-
|
30
|
-
hg.hostgroup_ansible_roles.each_with_index do |item, idx|
|
31
|
-
assert_equal(item.position, idx + 1)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
22
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import React, { useState } from 'react';
|
2
|
+
import { Tabs, Tab, TabTitleText, Label } from '@patternfly/react-core';
|
3
|
+
import { InfoCircleIcon } from '@patternfly/react-icons';
|
4
|
+
|
5
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
6
|
+
|
7
|
+
import './AnsibleHostDetail.scss';
|
8
|
+
|
9
|
+
const AnsibleHostDetail = props => {
|
10
|
+
// https://projects.theforeman.org/issues/32398
|
11
|
+
const [activeTab] = useState('variables');
|
12
|
+
|
13
|
+
return (
|
14
|
+
<Tabs activeKey={activeTab} isSecondary>
|
15
|
+
<Tab
|
16
|
+
eventKey="variables"
|
17
|
+
title={<TabTitleText>{__('Variables')}</TabTitleText>}
|
18
|
+
>
|
19
|
+
<div className="host-details-tab-item">
|
20
|
+
<div className="ansible-host-detail">
|
21
|
+
<Label
|
22
|
+
color="blue"
|
23
|
+
icon={<InfoCircleIcon />}
|
24
|
+
style={{ marginTop: '1.5rem' }}
|
25
|
+
>
|
26
|
+
Ansible Variables coming soon!
|
27
|
+
</Label>
|
28
|
+
</div>
|
29
|
+
</div>
|
30
|
+
</Tab>
|
31
|
+
</Tabs>
|
32
|
+
);
|
33
|
+
};
|
34
|
+
|
35
|
+
export default AnsibleHostDetail;
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { render, screen } from '@testing-library/react';
|
3
|
+
import '@testing-library/jest-dom';
|
4
|
+
|
5
|
+
import AnsibleHostDetail from './';
|
6
|
+
|
7
|
+
describe('AnsibleHostDetail', () => {
|
8
|
+
it('should show content', () => {
|
9
|
+
render(<AnsibleHostDetail />);
|
10
|
+
expect(
|
11
|
+
screen.getByText('Ansible Variables coming soon!')
|
12
|
+
).toBeInTheDocument();
|
13
|
+
});
|
14
|
+
});
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
exports[`AnsiblePermissionDenied should render 1`] = `
|
4
4
|
<EmptyStatePattern
|
5
|
+
action={null}
|
5
6
|
description={
|
6
7
|
<span>
|
7
8
|
You are not authorized to perform this action.
|
@@ -22,5 +23,6 @@ exports[`AnsiblePermissionDenied should render 1`] = `
|
|
22
23
|
header="Permission Denied"
|
23
24
|
icon="lock"
|
24
25
|
iconType="fa"
|
26
|
+
secondaryActions={Array []}
|
25
27
|
/>
|
26
28
|
`;
|
data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AssignedRolesList.test.js.snap
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
2
|
|
3
3
|
exports[`AssignedRolesList should render 1`] = `
|
4
|
-
<DndProvider
|
4
|
+
<Memo(DndProvider)
|
5
5
|
backend={[Function]}
|
6
6
|
>
|
7
7
|
<ListView
|
8
8
|
className=""
|
9
9
|
>
|
10
|
-
<
|
10
|
+
<DropTarget(DragSource(Orderable(AnsibleRole)))
|
11
11
|
icon="fa fa-minus-circle"
|
12
12
|
index={0}
|
13
13
|
key="1"
|
@@ -21,7 +21,7 @@ exports[`AssignedRolesList should render 1`] = `
|
|
21
21
|
}
|
22
22
|
}
|
23
23
|
/>
|
24
|
-
<
|
24
|
+
<DropTarget(DragSource(Orderable(AnsibleRole)))
|
25
25
|
icon="fa fa-minus-circle"
|
26
26
|
index={1}
|
27
27
|
key="2"
|
@@ -60,5 +60,5 @@ exports[`AssignedRolesList should render 1`] = `
|
|
60
60
|
}
|
61
61
|
/>
|
62
62
|
</div>
|
63
|
-
</DndProvider>
|
63
|
+
</Memo(DndProvider)>
|
64
64
|
`;
|
@@ -8,9 +8,14 @@ exports[`AvailableRolesList should render 1`] = `
|
|
8
8
|
className="sticky-pagination"
|
9
9
|
>
|
10
10
|
<PaginationWrapper
|
11
|
+
className=""
|
12
|
+
disableNext={false}
|
13
|
+
disablePrev={false}
|
11
14
|
dropdownButtonId="available-ansible-roles-pagination-row-dropdown"
|
12
15
|
itemCount={2}
|
13
16
|
onChange={[Function]}
|
17
|
+
onPageSet={[Function]}
|
18
|
+
onPerPageSelect={[Function]}
|
14
19
|
pagination={
|
15
20
|
Object {
|
16
21
|
"page": 1,
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
|
3
|
+
import { addGlobalFill } from 'foremanReact/components/common/Fill/GlobalFill';
|
4
|
+
|
5
|
+
import AnsibleHostDetail from './components/AnsibleHostDetail';
|
6
|
+
|
7
|
+
addGlobalFill(
|
8
|
+
'host-details-page-tabs',
|
9
|
+
'Ansible',
|
10
|
+
<AnsibleHostDetail key="ansible-host-detail" />,
|
11
|
+
500
|
12
|
+
);
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman_ansible
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Lobato Garcia
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: foreman_ansible_core
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '3.0'
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '3.0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: acts_as_list
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -302,9 +288,6 @@ files:
|
|
302
288
|
- test/unit/hostgroup_ansible_role_test.rb
|
303
289
|
- test/unit/ignore_roles_test.rb
|
304
290
|
- test/unit/import_roles_and_variables.rb
|
305
|
-
- test/unit/lib/foreman_ansible_core/ansible_runner_test.rb
|
306
|
-
- test/unit/lib/foreman_ansible_core/command_creator_test.rb
|
307
|
-
- test/unit/lib/foreman_ansible_core/playbook_runner_test.rb
|
308
291
|
- test/unit/lib/proxy_api/ansible_test.rb
|
309
292
|
- test/unit/services/ansible_report_importer_test.rb
|
310
293
|
- test/unit/services/ansible_variables_importer_test.rb
|
@@ -317,12 +300,10 @@ files:
|
|
317
300
|
- test/unit/services/roles_importer_test.rb
|
318
301
|
- test/unit/services/structured_fact_importer_test.rb
|
319
302
|
- test/unit/services/ui_roles_importer_test.rb
|
320
|
-
- webpack/
|
321
|
-
- webpack/
|
322
|
-
- webpack/
|
323
|
-
- webpack/
|
324
|
-
- webpack/__mocks__/foremanReact/components/common/forms/OrderableSelect/helpers.js
|
325
|
-
- webpack/__mocks__/foremanReact/redux/API.js
|
303
|
+
- webpack/components/AnsibleHostDetail/AnsibleHostDetail.js
|
304
|
+
- webpack/components/AnsibleHostDetail/AnsibleHostDetail.scss
|
305
|
+
- webpack/components/AnsibleHostDetail/AnsibleHostDetail.test.js
|
306
|
+
- webpack/components/AnsibleHostDetail/index.js
|
326
307
|
- webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariables.js
|
327
308
|
- webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariables.scss
|
328
309
|
- webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariablesActions.js
|
@@ -368,13 +349,14 @@ files:
|
|
368
349
|
- webpack/components/AnsibleRolesSwitcher/components/withProtectedView.js
|
369
350
|
- webpack/components/AnsibleRolesSwitcher/index.js
|
370
351
|
- webpack/components/ReportJsonViewer.js
|
352
|
+
- webpack/global_index.js
|
371
353
|
- webpack/index.js
|
372
354
|
- webpack/reducer.js
|
373
355
|
homepage: https://github.com/theforeman/foreman_ansible
|
374
356
|
licenses:
|
375
357
|
- GPL-3.0
|
376
358
|
metadata: {}
|
377
|
-
post_install_message:
|
359
|
+
post_install_message:
|
378
360
|
rdoc_options: []
|
379
361
|
require_paths:
|
380
362
|
- lib
|
@@ -390,7 +372,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
390
372
|
version: '0'
|
391
373
|
requirements: []
|
392
374
|
rubygems_version: 3.1.2
|
393
|
-
signing_key:
|
375
|
+
signing_key:
|
394
376
|
specification_version: 4
|
395
377
|
summary: Ansible integration with Foreman (theforeman.org)
|
396
378
|
test_files:
|
@@ -399,8 +381,8 @@ test_files:
|
|
399
381
|
- test/factories/ansible_roles.rb
|
400
382
|
- test/factories/host_ansible_enhancements.rb
|
401
383
|
- test/fixtures/insights_playbook.yaml
|
402
|
-
- test/fixtures/report.json
|
403
384
|
- test/fixtures/sample_facts.json
|
385
|
+
- test/fixtures/report.json
|
404
386
|
- test/functional/ansible_roles_controller_test.rb
|
405
387
|
- test/functional/api/v2/ansible_inventories_controller_test.rb
|
406
388
|
- test/functional/api/v2/ansible_variables_controller_test.rb
|
@@ -419,24 +401,21 @@ test_files:
|
|
419
401
|
- test/unit/concerns/host_managed_extensions_test.rb
|
420
402
|
- test/unit/concerns/hostgroup_extensions_test.rb
|
421
403
|
- test/unit/helpers/ansible_reports_helper_test.rb
|
422
|
-
- test/unit/lib/foreman_ansible_core/command_creator_test.rb
|
423
|
-
- test/unit/lib/foreman_ansible_core/ansible_runner_test.rb
|
424
|
-
- test/unit/lib/foreman_ansible_core/playbook_runner_test.rb
|
425
404
|
- test/unit/lib/proxy_api/ansible_test.rb
|
426
405
|
- test/unit/services/ansible_report_importer_test.rb
|
427
|
-
- test/unit/services/fact_importer_test.rb
|
428
406
|
- test/unit/services/fact_sparser_test.rb
|
429
407
|
- test/unit/services/insights_plan_runner_test.rb
|
430
408
|
- test/unit/services/roles_importer_test.rb
|
431
409
|
- test/unit/services/structured_fact_importer_test.rb
|
410
|
+
- test/unit/services/fact_importer_test.rb
|
432
411
|
- test/unit/services/ansible_variables_importer_test.rb
|
433
412
|
- test/unit/services/ui_roles_importer_test.rb
|
434
413
|
- test/unit/services/api_roles_importer_test.rb
|
435
414
|
- test/unit/services/fact_parser_test.rb
|
436
415
|
- test/unit/services/inventory_creator_test.rb
|
416
|
+
- test/unit/ansible_provider_test.rb
|
437
417
|
- test/unit/host_ansible_role_test.rb
|
418
|
+
- test/unit/hostgroup_ansible_role_test.rb
|
438
419
|
- test/unit/import_roles_and_variables.rb
|
439
420
|
- test/unit/ignore_roles_test.rb
|
440
|
-
- test/unit/hostgroup_ansible_role_test.rb
|
441
|
-
- test/unit/ansible_provider_test.rb
|
442
421
|
- test/foreman_ansible/helpers/ansible_roles_helper_test.rb
|
@@ -1,51 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
|
5
|
-
module ForemanAnsibleCore
|
6
|
-
module Runner
|
7
|
-
class AnsibleRunnerTest < ActiveSupport::TestCase
|
8
|
-
describe AnsibleRunner do
|
9
|
-
it 'parses files without event data' do
|
10
|
-
content = <<~JSON
|
11
|
-
{"uuid": "a29d8592-f805-4d0e-b73d-7a53cc35a92e", "stdout": " [WARNING]: Consider using the yum module rather than running 'yum'. If you", "counter": 8, "end_line": 8, "runner_ident": "e2d9ae11-026a-4f9f-9679-401e4b852ab0", "start_line": 7, "event": "verbose"}
|
12
|
-
JSON
|
13
|
-
|
14
|
-
File.expects(:read).with('fake.json').returns(content)
|
15
|
-
runner = AnsibleRunner.allocate
|
16
|
-
runner.expects(:handle_broadcast_data)
|
17
|
-
assert runner.send(:handle_event_file, 'fake.json')
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe '#rebuild_secrets' do
|
22
|
-
let(:inventory) do
|
23
|
-
{ 'all' => { 'hosts' => ['foreman.example.com'] },
|
24
|
-
'_meta' => { 'hostvars' => { 'foreman.example.com' => {} } } }
|
25
|
-
end
|
26
|
-
let(:input) do
|
27
|
-
host_secrets = { 'ansible_password' => 'letmein', 'ansible_become_password' => 'iamroot' }
|
28
|
-
secrets = { 'per-host' => { 'foreman.example.com' => host_secrets } }
|
29
|
-
host_input = { 'input' => { 'action_input' => { 'secrets' => secrets } } }
|
30
|
-
{ 'foreman.example.com' => host_input }
|
31
|
-
end
|
32
|
-
let(:runner) { ForemanAnsibleCore::Runner::AnsibleRunner.allocate }
|
33
|
-
|
34
|
-
test 'uses secrets from inventory' do
|
35
|
-
test_inventory = inventory.merge('ssh_password' => 'sshpass', 'effective_user_password' => 'mypass')
|
36
|
-
rebuilt = runner.send(:rebuild_secrets, test_inventory, input)
|
37
|
-
host_vars = rebuilt.dig('_meta', 'hostvars', 'foreman.example.com')
|
38
|
-
assert_equal 'sshpass', host_vars['ansible_password']
|
39
|
-
assert_equal 'mypass', host_vars['ansible_become_password']
|
40
|
-
end
|
41
|
-
|
42
|
-
test 'host secrets are used when not overriden by inventory secrest' do
|
43
|
-
rebuilt = runner.send(:rebuild_secrets, inventory, input)
|
44
|
-
host_vars = rebuilt.dig('_meta', 'hostvars', 'foreman.example.com')
|
45
|
-
assert_equal 'letmein', host_vars['ansible_password']
|
46
|
-
assert_equal 'iamroot', host_vars['ansible_become_password']
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
|
5
|
-
class CommandCreatorTest < ActiveSupport::TestCase
|
6
|
-
let(:inventory_file) { 'test_inventory' }
|
7
|
-
let(:playbook_file) { 'test_palybook.yml' }
|
8
|
-
subject do
|
9
|
-
ForemanAnsibleCore::CommandCreator.new(inventory_file, playbook_file, {})
|
10
|
-
end
|
11
|
-
|
12
|
-
test 'returns a command array including the ansible-playbook command' do
|
13
|
-
assert command_parts.include?('ansible-playbook')
|
14
|
-
end
|
15
|
-
|
16
|
-
test 'the last argument is the playbook_file' do
|
17
|
-
assert command_parts.last == playbook_file
|
18
|
-
end
|
19
|
-
|
20
|
-
describe 'environment variables' do
|
21
|
-
let(:environment_variables) { subject.command.first }
|
22
|
-
|
23
|
-
test 'has a JSON_INVENTORY_FILE set' do
|
24
|
-
assert environment_variables['JSON_INVENTORY_FILE']
|
25
|
-
end
|
26
|
-
|
27
|
-
test 'has no ANSIBLE_CALLBACK_WHITELIST set by default' do
|
28
|
-
assert_not environment_variables['ANSIBLE_CALLBACK_WHITELIST']
|
29
|
-
end
|
30
|
-
|
31
|
-
test 'with a REX command it sets ANSIBLE_CALLBACK_WHITELIST to empty' do
|
32
|
-
set_command_options(:remote_execution_command, true)
|
33
|
-
assert environment_variables['ANSIBLE_CALLBACK_WHITELIST']
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
describe 'command options' do
|
38
|
-
it 'can have verbosity set' do
|
39
|
-
level = '3'
|
40
|
-
level_string = Array.new(level.to_i).map { 'v' }.join
|
41
|
-
set_command_options(:verbosity_level, level)
|
42
|
-
assert command_parts.any? do |part|
|
43
|
-
part == "-#{level_string}"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'can have a timeout set' do
|
48
|
-
timeout = '5555'
|
49
|
-
set_command_options(:timeout, timeout)
|
50
|
-
assert command_parts.include?(timeout)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
private
|
55
|
-
|
56
|
-
def command_parts
|
57
|
-
subject.command.flatten.map(&:to_s)
|
58
|
-
end
|
59
|
-
|
60
|
-
def set_command_options(option, value)
|
61
|
-
subject.instance_eval("@options[:#{option}] = \"#{value}\"",
|
62
|
-
__FILE__, __LINE__ - 1)
|
63
|
-
end
|
64
|
-
end
|
@@ -1,110 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
|
5
|
-
# Playbook Runner - this class uses foreman_tasks_core
|
6
|
-
# to run playbooks
|
7
|
-
class PlaybookRunnerTest < ActiveSupport::TestCase
|
8
|
-
context 'roles dir' do
|
9
|
-
test 'reads default when none provided' do
|
10
|
-
ForemanAnsibleCore::Runner::Playbook.any_instance.stubs(:unknown_hosts).
|
11
|
-
returns([])
|
12
|
-
File.expects(:exist?).with(Dir.home).returns(true)
|
13
|
-
ForemanAnsibleCore::Runner::Playbook.any_instance.expects(:rebuild_secrets).returns(nil)
|
14
|
-
runner = ForemanAnsibleCore::Runner::Playbook.new(nil, nil, :suspended_action => nil)
|
15
|
-
assert '/etc/ansible', runner.instance_variable_get('@ansible_dir')
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
context 'working_dir' do
|
20
|
-
setup do
|
21
|
-
ForemanAnsibleCore::Runner::Playbook.any_instance.stubs(:unknown_hosts).
|
22
|
-
returns([])
|
23
|
-
end
|
24
|
-
|
25
|
-
test 'creates temp one if not provided' do
|
26
|
-
Dir.expects(:mktmpdir)
|
27
|
-
File.expects(:exist?).with(Dir.home).returns(true)
|
28
|
-
ForemanAnsibleCore::Runner::Playbook.any_instance.expects(:rebuild_secrets).returns(nil)
|
29
|
-
ForemanAnsibleCore::Runner::Playbook.new(nil, nil, :suspended_action => nil)
|
30
|
-
end
|
31
|
-
|
32
|
-
test 'reads it when provided' do
|
33
|
-
settings = { :working_dir => '/foo', :ansible_dir => '/etc/foo' }
|
34
|
-
ForemanAnsibleCore.expects(:settings).returns(settings)
|
35
|
-
File.expects(:exist?).with(settings[:ansible_dir]).returns(true)
|
36
|
-
Dir.expects(:mktmpdir).never
|
37
|
-
ForemanAnsibleCore::Runner::Playbook.any_instance.expects(:rebuild_secrets).returns(nil)
|
38
|
-
runner = ForemanAnsibleCore::Runner::Playbook.new(nil, nil, :suspended_action => nil)
|
39
|
-
assert '/foo', runner.instance_variable_get('@working_dir')
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
context 'TOFU policy' do # Trust On First Use
|
44
|
-
setup do
|
45
|
-
@inventory = { 'all' => { 'hosts' => ['foreman.example.com'] } }
|
46
|
-
@output = StringIO.new
|
47
|
-
logger = Logger.new(@output)
|
48
|
-
ForemanAnsibleCore::Runner::Playbook.any_instance.stubs(:logger).
|
49
|
-
returns(logger)
|
50
|
-
end
|
51
|
-
|
52
|
-
test 'ignores known hosts' do
|
53
|
-
Net::SSH::KnownHosts.expects(:search_for).
|
54
|
-
with('foreman.example.com').returns(['somekey'])
|
55
|
-
ForemanAnsibleCore::Runner::Playbook.any_instance.
|
56
|
-
expects(:add_to_known_hosts).never
|
57
|
-
ForemanAnsibleCore::Runner::Playbook.any_instance.expects(:rebuild_secrets).returns(@inventory)
|
58
|
-
ForemanAnsibleCore::Runner::Playbook.new(@inventory, nil, :suspended_action => nil)
|
59
|
-
end
|
60
|
-
|
61
|
-
test 'adds unknown hosts to known_hosts' do
|
62
|
-
Net::SSH::KnownHosts.expects(:search_for).
|
63
|
-
with('foreman.example.com').returns([])
|
64
|
-
ForemanAnsibleCore::Runner::Playbook.any_instance.
|
65
|
-
expects(:add_to_known_hosts).with('foreman.example.com')
|
66
|
-
ForemanAnsibleCore::Runner::Playbook.any_instance.expects(:rebuild_secrets).returns(@inventory)
|
67
|
-
ForemanAnsibleCore::Runner::Playbook.new(@inventory, nil, :suspended_action => nil)
|
68
|
-
end
|
69
|
-
|
70
|
-
test 'logs error when it cannot add to known_hosts' do
|
71
|
-
Net::SSH::KnownHosts.expects(:search_for).
|
72
|
-
with('foreman.example.com').returns([])
|
73
|
-
Net::SSH::Transport::Session.expects(:new).with('foreman.example.com').
|
74
|
-
raises(Net::Error)
|
75
|
-
ForemanAnsibleCore::Runner::Playbook.any_instance.expects(:rebuild_secrets).returns(@inventory)
|
76
|
-
ForemanAnsibleCore::Runner::Playbook.new(@inventory, nil, :suspended_action => nil)
|
77
|
-
assert_match(
|
78
|
-
/ERROR.*Failed to save host key for foreman.example.com: Net::Error/,
|
79
|
-
@output.string
|
80
|
-
)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
context 'rebuild secrets' do
|
85
|
-
let(:inventory) do
|
86
|
-
{ 'all' => { 'hosts' => ['foreman.example.com'] },
|
87
|
-
'_meta' => { 'hostvars' => { 'foreman.example.com' => {} } } }
|
88
|
-
end
|
89
|
-
let(:secrets) do
|
90
|
-
host_secrets = { 'ansible_password' => 'letmein', 'ansible_become_password' => 'iamroot' }
|
91
|
-
{ 'per-host' => { 'foreman.example.com' => host_secrets } }
|
92
|
-
end
|
93
|
-
let(:runner) { ForemanAnsibleCore::Runner::Playbook.allocate }
|
94
|
-
|
95
|
-
test 'uses secrets from inventory' do
|
96
|
-
test_inventory = inventory.merge('ssh_password' => 'sshpass', 'effective_user_password' => 'mypass')
|
97
|
-
rebuilt = runner.send(:rebuild_secrets, test_inventory, secrets)
|
98
|
-
host_vars = rebuilt.dig('_meta', 'hostvars', 'foreman.example.com')
|
99
|
-
assert_equal 'sshpass', host_vars['ansible_password']
|
100
|
-
assert_equal 'mypass', host_vars['ansible_become_password']
|
101
|
-
end
|
102
|
-
|
103
|
-
test 'host secrets are used when not overriden by inventory secrest' do
|
104
|
-
rebuilt = runner.send(:rebuild_secrets, inventory, secrets)
|
105
|
-
host_vars = rebuilt.dig('_meta', 'hostvars', 'foreman.example.com')
|
106
|
-
assert_equal 'letmein', host_vars['ansible_password']
|
107
|
-
assert_equal 'iamroot', host_vars['ansible_become_password']
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
@@ -1 +0,0 @@
|
|
1
|
-
export const translate = s => s;
|
@@ -1,13 +0,0 @@
|
|
1
|
-
import { camelCase } from 'lodash';
|
2
|
-
|
3
|
-
export const propsToCamelCase = ob =>
|
4
|
-
propsToCase(camelCase, 'propsToCamelCase only takes objects', ob);
|
5
|
-
|
6
|
-
const propsToCase = (casingFn, errorMsg, ob) => {
|
7
|
-
if (typeof ob !== 'object') throw Error(errorMsg);
|
8
|
-
|
9
|
-
return Object.keys(ob).reduce((memo, key) => {
|
10
|
-
memo[casingFn(key)] = ob[key];
|
11
|
-
return memo;
|
12
|
-
}, {});
|
13
|
-
};
|