foreman_ansible 2.3.2 → 2.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/foreman_ansible/foreman-ansible.css +4 -0
- data/app/controllers/ansible_variables_controller.rb +28 -6
- data/app/controllers/api/v2/ansible_variables_controller.rb +9 -1
- data/app/controllers/concerns/foreman/controller/parameters/ansible_variable.rb +2 -1
- data/app/controllers/ui_ansible_roles_controller.rb +14 -0
- data/app/helpers/foreman_ansible/ansible_roles_helper.rb +19 -1
- data/app/models/ansible_role.rb +1 -0
- data/app/models/ansible_variable.rb +8 -3
- data/app/services/foreman_ansible/variables_importer.rb +61 -30
- data/app/views/ansible_roles/welcome.html.erb +1 -1
- data/app/views/ansible_variables/_fields.erb +12 -5
- data/app/views/ansible_variables/import.html.erb +4 -1
- data/app/views/ansible_variables/index.html.erb +8 -3
- data/app/views/ansible_variables/new.html.erb +17 -0
- data/app/views/api/v2/ansible_variables/create.json.rabl +3 -0
- data/app/views/api/v2/ansible_variables/show.json.rabl +1 -1
- data/app/views/foreman_ansible/ansible_roles/_select_tab_content.html.erb +13 -13
- data/app/views/ui_ansible_roles/index.json.rabl +3 -0
- data/app/views/ui_ansible_roles/main.json.rabl +3 -0
- data/app/views/ui_ansible_roles/show.json.rabl +3 -0
- data/config/routes.rb +4 -2
- data/db/migrate/20190318094437_add_imported_attr_to_ansible_variables.rb +15 -0
- data/lib/foreman_ansible/register.rb +13 -2
- data/lib/foreman_ansible/version.rb +1 -1
- data/package.json +50 -9
- data/test/factories/ansible_variables.rb +1 -0
- data/test/functional/ansible_variables_controller_test.rb +10 -0
- data/test/functional/api/v2/ansible_variables_controller_test.rb +10 -0
- data/test/functional/ui_ansible_roles_controller_test.rb +14 -0
- data/test/unit/services/ansible_variables_importer_test.rb +20 -3
- data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +2 -0
- data/webpack/__mocks__/foremanReact/components/common/EmptyState.js +5 -0
- data/webpack/components/AnsibleRolesSwitcher/AnsibleRolesSwitcher.js +140 -0
- data/webpack/components/AnsibleRolesSwitcher/AnsibleRolesSwitcher.scss +45 -0
- data/webpack/components/AnsibleRolesSwitcher/AnsibleRolesSwitcherActions.js +69 -0
- data/webpack/components/AnsibleRolesSwitcher/AnsibleRolesSwitcherConstants.js +7 -0
- data/webpack/components/AnsibleRolesSwitcher/AnsibleRolesSwitcherHelpers.js +7 -0
- data/webpack/components/AnsibleRolesSwitcher/AnsibleRolesSwitcherReducer.js +69 -0
- data/webpack/components/AnsibleRolesSwitcher/AnsibleRolesSwitcherSelectors.js +68 -0
- data/webpack/components/AnsibleRolesSwitcher/__fixtures__/ansibleRolesData.fixtures.js +20 -0
- data/webpack/components/AnsibleRolesSwitcher/__fixtures__/ansibleRolesSwitcherReducer.fixtures.js +36 -0
- data/webpack/components/AnsibleRolesSwitcher/__tests__/AnsibleRolesSwitcher.test.js +30 -0
- data/webpack/components/AnsibleRolesSwitcher/__tests__/AnsibleRolesSwitcherReducer.test.js +73 -0
- data/webpack/components/AnsibleRolesSwitcher/__tests__/AnsibleRolesSwitcherSelectors.test.js +43 -0
- data/webpack/components/AnsibleRolesSwitcher/__tests__/__snapshots__/AnsibleRolesSwitcher.test.js.snap +79 -0
- data/webpack/components/AnsibleRolesSwitcher/__tests__/__snapshots__/AnsibleRolesSwitcherReducer.test.js.snap +399 -0
- data/webpack/components/AnsibleRolesSwitcher/__tests__/__snapshots__/AnsibleRolesSwitcherSelectors.test.js.snap +60 -0
- data/webpack/components/AnsibleRolesSwitcher/components/AnsiblePermissionDenied.js +33 -0
- data/webpack/components/AnsibleRolesSwitcher/components/AnsiblePermissionDenied.test.js +9 -0
- data/webpack/components/AnsibleRolesSwitcher/components/AnsibleRole.js +56 -0
- data/webpack/components/AnsibleRolesSwitcher/components/AnsibleRole.test.js +26 -0
- data/webpack/components/AnsibleRolesSwitcher/components/AnsibleRoleActionButton.js +16 -0
- data/webpack/components/AnsibleRolesSwitcher/components/AnsibleRolesSwitcherError.js +32 -0
- data/webpack/components/AnsibleRolesSwitcher/components/AssignedRolesList.js +67 -0
- data/webpack/components/AnsibleRolesSwitcher/components/AssignedRolesList.test.js +19 -0
- data/webpack/components/AnsibleRolesSwitcher/components/AvailableRolesList.js +52 -0
- data/webpack/components/AnsibleRolesSwitcher/components/AvailableRolesList.test.js +22 -0
- data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AnsiblePermissionDenied.test.js.snap +26 -0
- data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AnsibleRole.test.js.snap +108 -0
- data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AssignedRolesList.test.js.snap +64 -0
- data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AvailableRolesList.test.js.snap +54 -0
- data/webpack/components/AnsibleRolesSwitcher/components/withProtectedView.js +14 -0
- data/webpack/components/AnsibleRolesSwitcher/index.js +44 -0
- data/webpack/components/ReportJsonViewer.js +11 -7
- data/webpack/index.js +14 -1
- data/webpack/reducer.js +7 -0
- data/webpack/test_setup.js +11 -0
- metadata +46 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1bc81f85be7efbc4ebb9636fc9bd550d54fb22f3
|
4
|
+
data.tar.gz: d89aa3d74ffb81ed88a678e5f139530bdec076aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 853c086e4c7a344844c2da7360221030dba7ea21fd9d65d0f387b3c76825af7b2bae258ca8914eeaecfee5756ca99fbfc0d6bf7580e96dff2f458a3e9d449162
|
7
|
+
data.tar.gz: af2d1693fc63a41a202a2de837a9ae678b1400fc5c5c3eda567d4211e7244ac4036880d061fa74681052b277f356f33840d25f1845f92c5f02cc599f318b3103
|
@@ -18,6 +18,19 @@ class AnsibleVariablesController < ::LookupKeysController
|
|
18
18
|
:per_page => params[:per_page])
|
19
19
|
end
|
20
20
|
|
21
|
+
def new
|
22
|
+
@ansible_variable = AnsibleVariable.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def create
|
26
|
+
@ansible_variable = AnsibleVariable.new(ansible_variable_params.merge(:imported => false))
|
27
|
+
if @ansible_variable.save
|
28
|
+
process_success
|
29
|
+
else
|
30
|
+
process_error
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
21
34
|
def import
|
22
35
|
import_roles = @importer_roles.import_role_names
|
23
36
|
import_roles[:new_roles] = import_roles[:new]
|
@@ -27,11 +40,12 @@ class AnsibleVariablesController < ::LookupKeysController
|
|
27
40
|
end
|
28
41
|
|
29
42
|
def confirm_import
|
30
|
-
results = @importer.finish_import(new_vars, old_vars)
|
31
|
-
|
43
|
+
results = @importer.finish_import(new_vars, old_vars, updated_vars)
|
44
|
+
success _(
|
32
45
|
"Import of variables successfully finished.\n"\
|
33
|
-
"Added: #{results[:added].
|
34
|
-
"Removed: #{results[:obsolete].
|
46
|
+
"Added: #{results[:added].count} \n "\
|
47
|
+
"Removed: #{results[:obsolete].count} \n"\
|
48
|
+
"Updated: #{results[:updated].count}"
|
35
49
|
)
|
36
50
|
redirect_to ansible_variables_path
|
37
51
|
end
|
@@ -49,11 +63,19 @@ class AnsibleVariablesController < ::LookupKeysController
|
|
49
63
|
end
|
50
64
|
|
51
65
|
def new_vars
|
52
|
-
|
66
|
+
fetch_vars :new
|
53
67
|
end
|
54
68
|
|
55
69
|
def old_vars
|
56
|
-
|
70
|
+
fetch_vars :obsolete
|
71
|
+
end
|
72
|
+
|
73
|
+
def updated_vars
|
74
|
+
fetch_vars :update
|
75
|
+
end
|
76
|
+
|
77
|
+
def fetch_vars(key)
|
78
|
+
params.fetch(:changed, {}).fetch(key, {}).try(:as_json) || {}
|
57
79
|
end
|
58
80
|
|
59
81
|
def import_new_roles
|
@@ -6,6 +6,7 @@ module Api
|
|
6
6
|
class AnsibleVariablesController < ::Api::V2::BaseController
|
7
7
|
include ::Api::Version2
|
8
8
|
include Foreman::Controller::Parameters::VariableLookupKey
|
9
|
+
include Foreman::Controller::Parameters::AnsibleVariable
|
9
10
|
|
10
11
|
resource_description do
|
11
12
|
api_version 'v2'
|
@@ -36,7 +37,7 @@ module Api
|
|
36
37
|
def_param_group :ansible_variable do
|
37
38
|
param :ansible_variable, Hash, :required => true, :action_aware => true do
|
38
39
|
param :variable, String, :required => true, :desc => N_("Name of variable")
|
39
|
-
param :ansible_role_id, :number, :desc => N_("Role ID")
|
40
|
+
param :ansible_role_id, :number, :required => true, :desc => N_("Role ID")
|
40
41
|
param :default_value, :any_type, :of => LookupKey::KEY_TYPES, :desc => N_("Default value of variable")
|
41
42
|
param :hidden_value, :bool, :desc => N_("When enabled the parameter is hidden in the UI")
|
42
43
|
param :override_value_order, String, :desc => N_("The order in which values are resolved")
|
@@ -50,6 +51,13 @@ module Api
|
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
54
|
+
api :POST, '/ansible_variables', N_('Create Ansible variable')
|
55
|
+
param_group :ansible_variable, :as => :create
|
56
|
+
def create
|
57
|
+
@ansible_variable = AnsibleVariable.new(ansible_variable_params.merge(:imported => false))
|
58
|
+
process_response @ansible_variable.save
|
59
|
+
end
|
60
|
+
|
53
61
|
api :PUT, '/ansible_variables/:id', N_('Updates Ansible variable')
|
54
62
|
param :id, :identifier, :required => true
|
55
63
|
param_group :ansible_variable, :as => :update
|
@@ -11,7 +11,8 @@ module Foreman
|
|
11
11
|
class_methods do
|
12
12
|
def ansible_variable_params_filter
|
13
13
|
Foreman::ParameterFilter.new(::AnsibleVariable).tap do |filter|
|
14
|
-
filter.permit :
|
14
|
+
filter.permit :imported, :ansible_role_id,
|
15
|
+
:ansible_roles => [], :ansible_role_ids => [],
|
15
16
|
:ansible_role_names => [],
|
16
17
|
:param_classes => [], :param_classes_ids => [],
|
17
18
|
:param_classes_names => []
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class UiAnsibleRolesController < ::Api::V2::BaseController
|
2
|
+
def resource_name(resource = 'AnsibleRole')
|
3
|
+
super resource
|
4
|
+
end
|
5
|
+
|
6
|
+
def index
|
7
|
+
@ui_ansible_roles = resource_scope_for_index(:permission => :view_ansible_roles)
|
8
|
+
end
|
9
|
+
|
10
|
+
# restore original method from find_common to ignore resource nesting
|
11
|
+
def resource_scope(options = {})
|
12
|
+
@resource_scope ||= scope_for(resource_class, options)
|
13
|
+
end
|
14
|
+
end
|
@@ -5,12 +5,26 @@ module ForemanAnsible
|
|
5
5
|
module AnsibleRolesHelper
|
6
6
|
def ansible_proxy_links(hash, classes = nil)
|
7
7
|
SmartProxy.with_features('Ansible').map do |proxy|
|
8
|
-
display_link_if_authorized(_('
|
8
|
+
display_link_if_authorized(_('Import from %s') % proxy.name,
|
9
9
|
hash.merge(:proxy => proxy),
|
10
10
|
:class => classes)
|
11
11
|
end.flatten
|
12
12
|
end
|
13
13
|
|
14
|
+
def ansible_role_select(f, persisted)
|
15
|
+
blank_opt = persisted ? {} : { :include_blank => true }
|
16
|
+
select_items = persisted ? [f.object.ansible_role] : AnsibleRole.order(:name)
|
17
|
+
select_f f,
|
18
|
+
:ansible_role_id,
|
19
|
+
select_items,
|
20
|
+
:id,
|
21
|
+
:to_label,
|
22
|
+
blank_opt,
|
23
|
+
:label => _("Ansible Role"),
|
24
|
+
:disabled => persisted,
|
25
|
+
:required => true
|
26
|
+
end
|
27
|
+
|
14
28
|
def ansible_proxy_import(hash)
|
15
29
|
select_action_button(_('Import'),
|
16
30
|
{ :primary => true, :class => 'roles-import' },
|
@@ -20,5 +34,9 @@ module ForemanAnsible
|
|
20
34
|
def import_time(role)
|
21
35
|
_('%s ago') % time_ago_in_words(role.updated_at)
|
22
36
|
end
|
37
|
+
|
38
|
+
def roles_attrs(roles)
|
39
|
+
roles.map { |item| { :id => item.id, :name => item.name } }
|
40
|
+
end
|
23
41
|
end
|
24
42
|
end
|
data/app/models/ansible_role.rb
CHANGED
@@ -17,6 +17,7 @@ class AnsibleRole < ApplicationRecord
|
|
17
17
|
:class_name => 'AnsibleVariable'
|
18
18
|
|
19
19
|
scoped_search :on => :name, :complete_value => true
|
20
|
+
scoped_search :on => :id, :complete_value => false
|
20
21
|
scoped_search :on => :updated_at
|
21
22
|
scoped_search :relation => :hosts,
|
22
23
|
:on => :id, :rename => :host_id, :only_explicit => true
|
@@ -3,8 +3,9 @@
|
|
3
3
|
# Represents the variables used in Ansible to parameterize playbooks
|
4
4
|
class AnsibleVariable < LookupKey
|
5
5
|
belongs_to :ansible_role, :inverse_of => :ansible_variables
|
6
|
-
validates :
|
6
|
+
validates :ansible_role_id, :presence => true
|
7
7
|
scoped_search :on => :key, :aliases => [:name], :complete_value => true
|
8
|
+
scoped_search :on => :imported, :complete_value => { :true => true, :false => false }
|
8
9
|
scoped_search :relation => :ansible_role, :on => :name,
|
9
10
|
:complete_value => true, :rename => :ansible_role
|
10
11
|
|
@@ -12,8 +13,12 @@ class AnsibleVariable < LookupKey
|
|
12
13
|
true
|
13
14
|
end
|
14
15
|
|
15
|
-
def self.humanize_class_name
|
16
|
-
|
16
|
+
def self.humanize_class_name(options = nil)
|
17
|
+
if options.present?
|
18
|
+
super
|
19
|
+
else
|
20
|
+
"Ansible variable"
|
21
|
+
end
|
17
22
|
end
|
18
23
|
|
19
24
|
def editable_by_user?
|
@@ -6,6 +6,17 @@ module ForemanAnsible
|
|
6
6
|
class VariablesImporter
|
7
7
|
include ::ForemanAnsible::ProxyAPI
|
8
8
|
|
9
|
+
VARIABLE_TYPES = {
|
10
|
+
'TrueClass' => 'boolean',
|
11
|
+
'FalseClass' => 'boolean',
|
12
|
+
'Integer' => 'integer',
|
13
|
+
'Fixnum' => 'integer',
|
14
|
+
'Float' => 'real',
|
15
|
+
'Array' => 'array',
|
16
|
+
'Hash' => 'hash',
|
17
|
+
'String' => 'string'
|
18
|
+
}.freeze
|
19
|
+
|
9
20
|
def initialize(proxy = nil)
|
10
21
|
@ansible_proxy = proxy
|
11
22
|
end
|
@@ -34,11 +45,15 @@ module ForemanAnsible
|
|
34
45
|
end
|
35
46
|
|
36
47
|
def initialize_variables(variables, role)
|
37
|
-
variables.map do |
|
48
|
+
variables.map do |variable_name, variable_default|
|
38
49
|
variable = AnsibleVariable.find_or_initialize_by(
|
39
|
-
:key =>
|
40
|
-
# :key_type, :default_value, :required
|
50
|
+
:key => variable_name
|
41
51
|
)
|
52
|
+
if variable.new_record?
|
53
|
+
variable.assign_attributes(:default_value => variable_default,
|
54
|
+
:key_type => infer_key_type(variable_default),
|
55
|
+
:imported => true)
|
56
|
+
end
|
42
57
|
variable.ansible_role = role
|
43
58
|
variable.valid? ? variable : nil
|
44
59
|
end
|
@@ -46,45 +61,48 @@ module ForemanAnsible
|
|
46
61
|
|
47
62
|
def detect_changes(imported)
|
48
63
|
changes = {}.with_indifferent_access
|
49
|
-
|
50
|
-
changes[:
|
64
|
+
persisted, changes[:new] = imported.partition { |role| role.id.present? }
|
65
|
+
changes[:update], _old = persisted.partition(&:changed?)
|
66
|
+
changes[:obsolete] = AnsibleVariable.where.not(:id => persisted.pluck(:id), :imported => false)
|
51
67
|
changes
|
52
68
|
end
|
53
69
|
|
54
|
-
def finish_import(new, obsolete)
|
55
|
-
results = { :added => [], :obsolete => [] }
|
70
|
+
def finish_import(new, obsolete, update)
|
71
|
+
results = { :added => [], :obsolete => [], :updated => [] }
|
56
72
|
results[:added] = create_new_variables(new) if new.present?
|
57
73
|
results[:obsolete] = delete_old_variables(obsolete) if obsolete.present?
|
74
|
+
results[:updated] = update_variables(update) if update.present?
|
58
75
|
results
|
59
76
|
end
|
60
77
|
|
61
|
-
def create_new_variables(
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
variable.save
|
70
|
-
added << variable.key
|
71
|
-
end
|
78
|
+
def create_new_variables(variables)
|
79
|
+
iterate_over_variables(variables) do |role, memo, attrs|
|
80
|
+
variable = AnsibleVariable.new(
|
81
|
+
JSON.parse(attrs)['ansible_variable']
|
82
|
+
)
|
83
|
+
variable.ansible_role = ::AnsibleRole.find_by(:name => role)
|
84
|
+
variable.save
|
85
|
+
memo << variable
|
72
86
|
end
|
73
|
-
added
|
74
87
|
end
|
75
88
|
|
76
|
-
def
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
89
|
+
def update_variables(variables)
|
90
|
+
iterate_over_variables(variables) do |_role, memo, attrs|
|
91
|
+
attributes = JSON.parse(attrs)['ansible_variable']
|
92
|
+
var = AnsibleVariable.find attributes['id']
|
93
|
+
var.update(attributes)
|
94
|
+
memo << var
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def delete_old_variables(variables)
|
99
|
+
iterate_over_variables(variables) do |_role, memo, attrs|
|
100
|
+
variable = AnsibleVariable.find(
|
101
|
+
JSON.parse(attrs)['ansible_variable']['id']
|
102
|
+
)
|
103
|
+
memo << variable.key
|
104
|
+
variable.destroy
|
86
105
|
end
|
87
|
-
removed
|
88
106
|
end
|
89
107
|
|
90
108
|
private
|
@@ -96,5 +114,18 @@ module ForemanAnsible
|
|
96
114
|
def remote_variables
|
97
115
|
proxy_api.all_variables
|
98
116
|
end
|
117
|
+
|
118
|
+
def infer_key_type(value)
|
119
|
+
VARIABLE_TYPES[value.class.to_s] || 'string'
|
120
|
+
end
|
121
|
+
|
122
|
+
def iterate_over_variables(variables)
|
123
|
+
variables.reduce([]) do |memo, (role, vars)|
|
124
|
+
vars.map do |_key, attrs|
|
125
|
+
yield role, memo, attrs if block_given?
|
126
|
+
memo
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
99
130
|
end
|
100
131
|
end
|
@@ -7,7 +7,7 @@
|
|
7
7
|
<p><%= _('No ansible roles were found in Foreman. If you want to assign roles to your hosts,
|
8
8
|
you have to import them first.').html_safe %>
|
9
9
|
</p>
|
10
|
-
<p><%= link_to(_('Learn more about this in the documentation.'), documentation_url('#4.1ImportingRoles', :root_url => ansible_doc_url)) %></p>
|
10
|
+
<p><%= link_to(_('Learn more about this in the documentation.'), documentation_url('#4.1ImportingRoles', :root_url => ansible_doc_url), target: '_blank') %></p>
|
11
11
|
<div class="blank-slate-pf-secondary-action">
|
12
12
|
<%= ansible_proxy_import(hash_for_import_ansible_roles_path) %>
|
13
13
|
</div>
|
@@ -1,10 +1,11 @@
|
|
1
1
|
<div id='<%= f.object.to_param %>' class='tab-pane fields'>
|
2
2
|
<fieldset>
|
3
|
-
|
4
|
-
|
5
|
-
<%= f
|
3
|
+
<% is_imported = f.object.new_record? ? false : f.object.imported %>
|
4
|
+
<h2><%= is_imported ? _("Ansible Variable Details (Imported)") : _("Ansible Variable Details")%></h2>
|
5
|
+
<%= text_f f, :key, :disabled => f.object.persisted?, :size => "col-md-8" %>
|
6
6
|
<%= textarea_f f, :description, :rows => :auto, :size => "col-md-8", :class => "no-stretch" %>
|
7
|
-
<%=
|
7
|
+
<%= ansible_role_select f, f.object.persisted? %>
|
8
|
+
|
8
9
|
</fieldset>
|
9
10
|
<fieldset>
|
10
11
|
<h2><%= _("Default Behavior") %></h2>
|
@@ -12,7 +13,13 @@
|
|
12
13
|
<%= checkbox_f(f, :override, :onchange => 'toggleOverrideValue(this)', :size => "col-md-8",
|
13
14
|
:label_help => _('Mark the variable to be managed by Foreman. When the Ansible role of this variable is assigned to a host, the default value will be added to Ansible inventory as a host variable. Specify matchers to set a different value for such variable.')
|
14
15
|
) %>
|
15
|
-
|
16
|
+
|
17
|
+
<% version = Foreman::Version.new %>
|
18
|
+
<% if version.major.to_i >= 1 && version.minor.to_i >= 22 %>
|
19
|
+
<%= param_type_selector(f, false, :onchange => 'keyTypeChange(this)', :disabled => !f.object.override) %>
|
20
|
+
<% else %>
|
21
|
+
<%= param_type_selector(f, :onchange => 'keyTypeChange(this)', :disabled => !f.object.override) %>
|
22
|
+
<% end %>
|
16
23
|
<%= textarea_f f, :default_value, :value => f.object.default_value_before_type_cast, :size => "col-md-8",
|
17
24
|
:disabled => (!f.object.override || f.object.omit),
|
18
25
|
:input_group_btn => fullscreen_input,
|
@@ -9,6 +9,9 @@
|
|
9
9
|
<%= link_to_function(icon_text("check", _("Obsolete")),
|
10
10
|
"toggleCheckboxesBySelector('.variable_select_boxes_obsolete')",
|
11
11
|
:title => _("Check/Uncheck obsolete")) %>
|
12
|
+
<%= link_to_function(icon_text("check", _("Update")),
|
13
|
+
"toggleCheckboxesBySelector('.variable_select_boxes_update')",
|
14
|
+
:title => _("Check/Uncheck update")) %>
|
12
15
|
</h6>
|
13
16
|
<table class="<%= table_css_classes %>">
|
14
17
|
<thead>
|
@@ -39,7 +42,7 @@
|
|
39
42
|
<td><%= variable.ansible_role.hosts.count %></td>
|
40
43
|
<td><%= variable.ansible_role.hostgroups.count %></td>
|
41
44
|
<td>
|
42
|
-
<%= { "new" => _("Add"), "obsolete" => _("Remove") }[kind] %>
|
45
|
+
<%= { "new" => _("Add"), "obsolete" => _("Remove"), "update" => _("Update") }[kind] %>
|
43
46
|
</td>
|
44
47
|
</tr>
|
45
48
|
<% end %>
|
@@ -1,14 +1,18 @@
|
|
1
1
|
<% title _("Ansible Variables") %>
|
2
|
+
<%= stylesheet 'foreman_ansible/foreman-ansible' %>
|
2
3
|
|
3
|
-
|
4
|
-
|
4
|
+
<%= title_actions ansible_proxy_import(hash_for_import_ansible_variables_path),
|
5
|
+
display_link_if_authorized(_('New Ansible Variable'), hash_for_new_ansible_variable_path, :class => "btn btn-default no-float"),
|
6
|
+
documentation_button('#4.3Variables', :root_url => ansible_doc_url)
|
7
|
+
%>
|
5
8
|
|
6
9
|
<table class="<%= table_css_classes 'table-fixed' %>">
|
7
10
|
<thead>
|
8
11
|
<tr>
|
9
12
|
<th class='col-md-6'><%= sort :name, :as => s_('Variable|Name') %></th>
|
10
13
|
<th class='col-md-2'><%= sort :ansible_role, :as => s_('Variable|Role') %></th>
|
11
|
-
<th class='col-md-
|
14
|
+
<th class='col-md-1'><%= _('Type') %></th>
|
15
|
+
<th class='col-md-1'><%= sort :imported, :as => _('Imported?') %></th>
|
12
16
|
<th class='col-md-2'><%= _('Actions') %></th>
|
13
17
|
</tr>
|
14
18
|
</thead>
|
@@ -27,6 +31,7 @@
|
|
27
31
|
hash_for_ansible_variables_path(:search => "ansible_role = #{variable.ansible_role}")
|
28
32
|
) %></td>
|
29
33
|
<td class="ellipsis"><%= variable.key_type || 'string' %></td>
|
34
|
+
<td align='center'><%= checked_icon variable.imported %></td>
|
30
35
|
<td class="ellipsis">
|
31
36
|
<% links = [
|
32
37
|
display_delete_if_authorized(
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<%= breadcrumbs(
|
2
|
+
:items => [
|
3
|
+
{
|
4
|
+
:caption => _('Ansible Variables'),
|
5
|
+
:url => url_for(ansible_variables_path)
|
6
|
+
},
|
7
|
+
{
|
8
|
+
:caption => _('Create Ansible Variable')
|
9
|
+
}
|
10
|
+
],
|
11
|
+
:switchable => false
|
12
|
+
) %>
|
13
|
+
<% title(_('Create Ansible Variable')) %>
|
14
|
+
<%= form_for(@ansible_variable) do |f| %>
|
15
|
+
<%= render 'fields', :f => f %>
|
16
|
+
<%= submit_or_cancel f %>
|
17
|
+
<% end %>
|
@@ -5,7 +5,7 @@ attributes :id, :variable, :ansible_role, :ansible_role_id, :description, :overr
|
|
5
5
|
:variable_type, :hidden_value?, :validator_type,
|
6
6
|
:validator_rule, :merge_overrides, :merge_default,
|
7
7
|
:avoid_duplicates, :override_value_order, :created_at, :updated_at,
|
8
|
-
:default_value
|
8
|
+
:default_value, :imported
|
9
9
|
|
10
10
|
node do |ansible_variable|
|
11
11
|
{
|
@@ -1,15 +1,15 @@
|
|
1
|
+
<%= webpacked_plugins_js_for :foreman_ansible %>
|
2
|
+
<%= webpacked_plugins_css_for :foreman_ansible %>
|
3
|
+
|
1
4
|
<div class='tab-pane' id='ansible_roles'>
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
'or by clicking on the Play Roles button on the Host page ').html_safe
|
13
|
-
},
|
14
|
-
{ 'data-inheriteds' => f.object.inherited_ansible_roles.map(&:id).to_json }) %>
|
5
|
+
<div id='ansible_roles_switcher'></div>
|
6
|
+
<% roles = f.object.is_a?(Hostgroup) ? roles_attrs(f.object.inherited_and_own_ansible_roles) : roles_attrs(f.object.all_ansible_roles) %>
|
7
|
+
<% class_name = f.object.is_a?(Hostgroup) ? 'Hostgroup' : 'Host' %>
|
8
|
+
<%= mount_react_component('AnsibleRolesSwitcher', '#ansible_roles_switcher', { :initialAssignedRoles => roles,
|
9
|
+
:inheritedRoleIds => f.object.inherited_ansible_roles.map(&:id),
|
10
|
+
:availableRolesUrl => ui_ansible_roles_path,
|
11
|
+
:resourceId => f.object.id,
|
12
|
+
:resourceName => class_name,
|
13
|
+
:canView => User.current.can?(:view_ansible_roles)
|
14
|
+
}.to_json) %>
|
15
15
|
</div>
|
data/config/routes.rb
CHANGED
@@ -58,7 +58,9 @@ Rails.application.routes.draw do
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
resources :
|
61
|
+
resources :ui_ansible_roles, :only => [:index]
|
62
|
+
|
63
|
+
resources :ansible_variables, :except => [:show] do
|
62
64
|
resources :lookup_values, :only => [:index, :create, :update, :destroy]
|
63
65
|
collection do
|
64
66
|
get :import
|
@@ -82,7 +84,7 @@ Rails.application.routes.draw do
|
|
82
84
|
end
|
83
85
|
end
|
84
86
|
|
85
|
-
resources :ansible_variables, :only => [:show, :index, :destroy, :update] do
|
87
|
+
resources :ansible_variables, :only => [:show, :index, :destroy, :update, :create] do
|
86
88
|
collection do
|
87
89
|
put :import
|
88
90
|
put :obsolete
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class AddImportedAttrToAnsibleVariables < ActiveRecord::Migration[5.2]
|
2
|
+
def up
|
3
|
+
add_column :lookup_keys, :imported, :boolean
|
4
|
+
|
5
|
+
AnsibleVariable.find_in_batches do |batch|
|
6
|
+
batch.map do |variable|
|
7
|
+
variable.update_attribute :imported, true
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def down
|
13
|
+
remove_column :lookup_keys, :imported
|
14
|
+
end
|
15
|
+
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
# rubocop:disable BlockLength
|
4
4
|
Foreman::Plugin.register :foreman_ansible do
|
5
|
-
requires_foreman '>= 1.
|
5
|
+
requires_foreman '>= 1.21'
|
6
6
|
|
7
7
|
security_block :foreman_ansible do
|
8
8
|
permission :play_roles_on_host,
|
@@ -17,7 +17,8 @@ Foreman::Plugin.register :foreman_ansible do
|
|
17
17
|
:resource_type => 'Hostgroup'
|
18
18
|
permission :view_ansible_roles,
|
19
19
|
{ :ansible_roles => [:index, :auto_complete_search],
|
20
|
-
:'api/v2/ansible_roles' => [:index, :show, :fetch]
|
20
|
+
:'api/v2/ansible_roles' => [:index, :show, :fetch],
|
21
|
+
:ui_ansible_roles => [:index] },
|
21
22
|
:resource_type => 'AnsibleRole'
|
22
23
|
permission :destroy_ansible_roles,
|
23
24
|
{ :ansible_roles => [:destroy],
|
@@ -44,6 +45,12 @@ Foreman::Plugin.register :foreman_ansible do
|
|
44
45
|
:'api/v2/ansible_variables' => [:destroy, :obsolete]
|
45
46
|
},
|
46
47
|
:resource_type => 'AnsibleVariable'
|
48
|
+
permission :create_ansible_variables,
|
49
|
+
{
|
50
|
+
:ansible_variables => [:new, :create],
|
51
|
+
:'api/v2/ansible_variables' => [:create]
|
52
|
+
},
|
53
|
+
:resource_type => 'AnsibleVariable'
|
47
54
|
permission :import_ansible_variables,
|
48
55
|
{
|
49
56
|
:ansible_variables => [:import, :confirm_import],
|
@@ -69,6 +76,10 @@ Foreman::Plugin.register :foreman_ansible do
|
|
69
76
|
:view_ansible_roles, :destroy_ansible_roles,
|
70
77
|
:import_ansible_roles]
|
71
78
|
|
79
|
+
role 'Ansible Tower Inventory Reader',
|
80
|
+
[:view_hosts, :view_hostgroups, :view_facts],
|
81
|
+
'Permissions required for the user which is used by Ansible Tower Dynamic Inventory Item'
|
82
|
+
|
72
83
|
add_all_permissions_to_default_roles
|
73
84
|
extend_template_helpers ForemanAnsible::RendererMethods
|
74
85
|
allowed_template_helpers :insights_remediation
|