foreman_ansible 1.0 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of foreman_ansible might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Rakefile +6 -27
- data/app/controllers/ansible_roles_controller.rb +55 -0
- data/app/controllers/api/v2/ansible_roles_controller.rb +52 -0
- data/app/controllers/foreman_ansible/concerns/hosts_controller_extensions.rb +11 -10
- data/app/helpers/foreman_ansible/ansible_plugin_helper.rb +8 -0
- data/app/helpers/foreman_ansible/ansible_reports_helper.rb +6 -4
- data/app/helpers/foreman_ansible/ansible_roles_helper.rb +17 -3
- data/app/helpers/foreman_ansible/hosts_helper_extensions.rb +4 -3
- data/app/lib/actions/foreman_ansible/play_host_roles.rb +56 -0
- data/app/lib/actions/foreman_ansible/play_hosts_roles.rb +26 -0
- data/app/lib/proxy_api/ansible.rb +28 -0
- data/app/models/ansible_role.rb +8 -0
- data/app/models/concerns/foreman_ansible/has_many_ansible_roles.rb +13 -0
- data/app/models/concerns/foreman_ansible/host_managed_extensions.rb +5 -1
- data/app/models/concerns/foreman_ansible/hostgroup_extensions.rb +19 -0
- data/app/models/host_ansible_role.rb +0 -2
- data/app/models/hostgroup_ansible_role.rb +8 -0
- data/app/overrides/ansible_roles_tab.rb +2 -2
- data/app/overrides/hostgroup_ansible_roles_tab.rb +14 -0
- data/app/services/foreman_ansible/api_roles_importer.rb +16 -0
- data/app/services/foreman_ansible/fact_importer.rb +2 -1
- data/app/services/foreman_ansible/inventory_creator.rb +37 -5
- data/app/services/foreman_ansible/playbook_creator.rb +3 -4
- data/app/services/foreman_ansible/proxy_selector.rb +19 -0
- data/app/services/foreman_ansible/roles_importer.rb +42 -15
- data/app/services/foreman_ansible/ui_roles_importer.rb +26 -0
- data/app/views/ansible_roles/import.html.erb +51 -0
- data/app/views/ansible_roles/index.html.erb +30 -0
- data/app/views/ansible_roles/welcome.html.erb +14 -0
- data/app/views/api/v2/ansible_roles/import.json.rabl +3 -0
- data/app/views/api/v2/ansible_roles/index.json.rabl +3 -0
- data/app/views/api/v2/ansible_roles/obsolete.json.rabl +3 -0
- data/app/views/api/v2/ansible_roles/show.json.rabl +3 -0
- data/app/views/foreman_ansible/ansible_roles/_select_tab_content.html.erb +6 -0
- data/app/views/foreman_ansible/{hosts/_tab_title.html.erb → ansible_roles/_select_tab_title.html.erb} +0 -0
- data/config/routes.rb +25 -2
- data/db/migrate/20160705082036_create_ansible_role.rb +2 -1
- data/db/migrate/20160706074540_create_join_table_hosts_ansible_roles.rb +1 -0
- data/db/migrate/20160707195442_create_host_ansible_roles.rb +1 -0
- data/db/migrate/20160729094457_add_columns_to_ansible_role.rb +12 -0
- data/db/migrate/20160802153302_create_join_table_hostgroup_ansible_roles.rb +10 -0
- data/db/migrate/20160805094233_add_primary_key_hostgroup_ansible_roles.rb +6 -0
- data/db/seeds.d/{62-ansible_proxy_feature.rb → 62_ansible_proxy_feature.rb} +0 -0
- data/lib/foreman_ansible.rb +1 -0
- data/lib/foreman_ansible/engine.rb +54 -4
- data/lib/foreman_ansible/version.rb +1 -1
- data/locale/en/foreman_ansible.po +139 -2
- data/locale/foreman_ansible.pot +200 -8
- data/test/factories/ansible_proxy.rb +7 -0
- data/test/factories/ansible_roles.rb +2 -2
- data/test/fixtures/ansible_permissions.yml +11 -0
- data/test/functional/ansible_roles_controller_test.rb +16 -0
- data/test/functional/api/v2/ansible_roles_controller_test.rb +24 -0
- data/test/functional/hosts_controller_test.rb +65 -24
- data/test/support/fixture_support.rb +25 -0
- data/test/support/foreman_tasks/task.rb +47 -0
- data/test/support/foreman_test_helper_additions.rb +22 -0
- data/test/test_plugin_helper.rb +5 -2
- data/test/unit/ansible_role_test.rb +6 -2
- data/test/unit/concerns/host_managed_extensions_test.rb +37 -0
- data/test/unit/concerns/hostgroup_extensions_test.rb +36 -0
- data/test/unit/fact_importer_test.rb +11 -8
- data/test/unit/fact_parser_test.rb +2 -0
- data/test/unit/fact_sparser_test.rb +1 -0
- data/test/unit/helpers/foreman_ansible/ansible_reports_helper_test.rb +1 -0
- data/test/unit/host_ansible_role_test.rb +10 -0
- data/test/unit/hostgroup_ansible_role_test.rb +19 -0
- data/test/unit/lib/foreman_ansible_core/playbook_runner_test.rb +28 -0
- data/test/unit/lib/proxy_api/ansible_test.rb +23 -0
- data/test/unit/services/api_roles_importer_test.rb +28 -0
- data/test/unit/services/proxy_selector_test.rb +28 -0
- data/test/unit/services/roles_importer_test.rb +17 -0
- data/test/unit/services/ui_roles_importer_test.rb +30 -0
- metadata +108 -14
- data/app/jobs/foreman_ansible/run_playbook_job.rb +0 -28
- data/app/services/foreman_ansible/role_player.rb +0 -26
- data/app/views/foreman_ansible/hosts/_tab_content.html.erb +0 -4
- data/lib/tasks/foreman_ansible_tasks.rake +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7394d81e94f7dd6bfda57b0a539adc09a1c068e0
|
4
|
+
data.tar.gz: 87475c40db6d3a594517de1443878ffe107b85f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 48d0c08d791d3543d6cbf2341c6a3ed66ba9c0d4b9a8c9e5bbcc0344444ef9c8c94db91ae4b7bf193ef915c75d9162470877140c46cd9d3c44e110d3593d809b
|
7
|
+
data.tar.gz: 79df637cc5ce51f5f6d9ee40ae0587b18c4dc9f339ae0edd4d813dd97fcfe1965bc589d7c176fcabcbd202cd47d75a839695ed652a9636ff32e37175164e168b
|
data/Rakefile
CHANGED
@@ -4,37 +4,16 @@ begin
|
|
4
4
|
rescue LoadError
|
5
5
|
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
6
|
end
|
7
|
-
begin
|
8
|
-
require 'rdoc/task'
|
9
|
-
rescue LoadError
|
10
|
-
require 'rdoc/rdoc'
|
11
|
-
require 'rake/rdoctask'
|
12
|
-
RDoc::Task = Rake::RDocTask
|
13
|
-
end
|
14
|
-
|
15
|
-
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
-
rdoc.rdoc_dir = 'rdoc'
|
17
|
-
rdoc.title = 'ForemanAnsible'
|
18
|
-
rdoc.options << '--line-numbers'
|
19
|
-
rdoc.rdoc_files.include('README.rdoc')
|
20
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
-
end
|
22
|
-
|
23
|
-
APP_RAKEFILE = File.expand_path('../test/dummy/Rakefile', __FILE__)
|
24
|
-
|
25
|
-
Bundler::GemHelper.install_tasks
|
26
7
|
|
27
8
|
require 'rake/testtask'
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
9
|
+
Rake::TestTask.new("test:core") do |test|
|
10
|
+
test_dir = File.join(File.dirname(__FILE__), 'test/lib')
|
11
|
+
test.pattern = "#{test_dir}/**/*_test.rb"
|
12
|
+
test.libs << test_dir
|
13
|
+
test.verbose = false
|
14
|
+
test.warning = false
|
34
15
|
end
|
35
16
|
|
36
|
-
task :default => :test
|
37
|
-
|
38
17
|
begin
|
39
18
|
require 'rubocop/rake_task'
|
40
19
|
RuboCop::RakeTask.new
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# UI controller for ansible roles
|
2
|
+
class AnsibleRolesController < ::ApplicationController
|
3
|
+
include Foreman::Controller::AutoCompleteSearch
|
4
|
+
|
5
|
+
before_action :find_resource, :only => [:destroy]
|
6
|
+
before_action :find_proxy, :only => [:import]
|
7
|
+
before_action :create_importer, :only => [:import, :confirm_import]
|
8
|
+
|
9
|
+
def index
|
10
|
+
@ansible_roles = resource_base.search_for(params[:search],
|
11
|
+
:order => params[:order]).
|
12
|
+
paginate(:page => params[:page],
|
13
|
+
:per_page => params[:per_page])
|
14
|
+
end
|
15
|
+
|
16
|
+
def destroy
|
17
|
+
if @ansible_role.destroy
|
18
|
+
process_success
|
19
|
+
else
|
20
|
+
process_error
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def import
|
25
|
+
changed = @importer.import!
|
26
|
+
if changed.values.all?(&:empty?)
|
27
|
+
notice no_changed_roles_message
|
28
|
+
redirect_to ansible_roles_path
|
29
|
+
else
|
30
|
+
render :locals => { :changed => changed }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def confirm_import
|
35
|
+
@importer.finish_import(params[:changed])
|
36
|
+
notice _('Import of roles successfully finished.')
|
37
|
+
redirect_to ansible_roles_path
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def find_proxy
|
43
|
+
return nil unless params[:proxy]
|
44
|
+
@proxy = SmartProxy.authorized(:view_smart_proxies).find(params[:proxy])
|
45
|
+
end
|
46
|
+
|
47
|
+
def create_importer
|
48
|
+
@importer = ForemanAnsible::UiRolesImporter.new(@proxy)
|
49
|
+
end
|
50
|
+
|
51
|
+
def no_changed_roles_message
|
52
|
+
return _('No changes in roles detected.') unless @proxy.present?
|
53
|
+
_('No changes in roles detected on %s.') % @proxy.name
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Api
|
2
|
+
module V2
|
3
|
+
# API controller for Ansible Roles
|
4
|
+
class AnsibleRolesController < ::Api::V2::BaseController
|
5
|
+
include ::Api::Version2
|
6
|
+
|
7
|
+
before_action :find_resource, :only => [:show, :destroy]
|
8
|
+
before_action :find_proxy, :only => [:import, :obsolete]
|
9
|
+
before_action :create_importer, :only => [:import, :obsolete]
|
10
|
+
|
11
|
+
api :GET, '/ansible/ansible_roles/:id', N_('Show role')
|
12
|
+
param :id, :identifier, :required => true
|
13
|
+
def show
|
14
|
+
end
|
15
|
+
|
16
|
+
api :GET, '/ansible/ansible_roles', N_('List Ansible roles')
|
17
|
+
param_group :search_and_pagination, ::Api::V2::BaseController
|
18
|
+
def index
|
19
|
+
@ansible_roles = resource_scope_for_index
|
20
|
+
end
|
21
|
+
|
22
|
+
api :DELETE, '/ansible/ansible_roles/:id', N_('Deletes Ansible role')
|
23
|
+
param :id, :identifier, :required => true
|
24
|
+
def destroy
|
25
|
+
process_response @ansible_role.destroy
|
26
|
+
end
|
27
|
+
|
28
|
+
api :POST, '/ansible/ansible_roles/import', N_('Import Ansible roles')
|
29
|
+
param :proxy, Hash, N_('Smart Proxy to import from')
|
30
|
+
def import
|
31
|
+
@imported = @importer.import!
|
32
|
+
end
|
33
|
+
|
34
|
+
api :POST, '/ansible/ansible_roles/obsolete', N_('Obsolete Ansible roles')
|
35
|
+
param :proxy, Hash, N_('Smart Proxy to import from')
|
36
|
+
def obsolete
|
37
|
+
@obsoleted = @importer.obsolete!
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def find_proxy
|
43
|
+
return nil unless params[:proxy]
|
44
|
+
@proxy = SmartProxy.authorized(:view_smart_proxies).find(params[:proxy])
|
45
|
+
end
|
46
|
+
|
47
|
+
def create_importer
|
48
|
+
@importer = ForemanAnsible::ApiRolesImporter.new(@proxy)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -3,23 +3,24 @@ module ForemanAnsible
|
|
3
3
|
# Extra methods to enforce Ansible roles on a host or multiple hosts
|
4
4
|
module HostsControllerExtensions
|
5
5
|
extend ActiveSupport::Concern
|
6
|
+
include ForemanTasks::Triggers
|
6
7
|
|
7
8
|
def play_roles
|
8
9
|
find_resource
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
task = async_task(::Actions::ForemanAnsible::PlayHostRoles, @host)
|
11
|
+
redirect_to task
|
12
|
+
rescue Foreman::Exception => e
|
13
|
+
error e.message
|
14
|
+
redirect_to host_path(@host)
|
13
15
|
end
|
14
16
|
|
15
17
|
def multiple_play_roles
|
16
18
|
find_multiple
|
17
|
-
@hosts
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
redirect_to :hosts
|
19
|
+
task = async_task(::Actions::ForemanAnsible::PlayHostsRoles, @hosts)
|
20
|
+
redirect_to task
|
21
|
+
rescue Foreman::Exception => e
|
22
|
+
error e.message
|
23
|
+
redirect_to hosts_path
|
23
24
|
end
|
24
25
|
|
25
26
|
private
|
@@ -12,10 +12,12 @@ module ForemanAnsible
|
|
12
12
|
|
13
13
|
def ansible_module_message(log)
|
14
14
|
paragraph_style = 'margin:0px;font-family:Menlo,Monaco,Consolas,monospace'
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
safe_join(
|
16
|
+
JSON.parse(log.message.value).except('invocation').map do |name, value|
|
17
|
+
next if value.blank?
|
18
|
+
content_tag(:p, "#{name}: #{value}", :style => paragraph_style)
|
19
|
+
end
|
20
|
+
)
|
19
21
|
end
|
20
22
|
|
21
23
|
def ansible_report?(log)
|
@@ -1,9 +1,23 @@
|
|
1
1
|
module ForemanAnsible
|
2
2
|
# Small convenience to list all roles in the UI
|
3
3
|
module AnsibleRolesHelper
|
4
|
-
def
|
5
|
-
|
6
|
-
|
4
|
+
def ansible_proxy_links(hash, classes = nil)
|
5
|
+
links = SmartProxy.with_features('Ansible').map do |proxy|
|
6
|
+
display_link_if_authorized(_('Import from %s') % proxy.name,
|
7
|
+
hash.merge(:proxy => proxy),
|
8
|
+
:class => classes)
|
9
|
+
end.flatten
|
10
|
+
links.unshift display_link_if_authorized(_('Import from Foreman host'),
|
11
|
+
hash,
|
12
|
+
:class => classes)
|
13
|
+
end
|
14
|
+
|
15
|
+
def ansible_proxy_import(hash)
|
16
|
+
select_action_button(_('Import'), {}, ansible_proxy_links(hash))
|
17
|
+
end
|
18
|
+
|
19
|
+
def import_time(role)
|
20
|
+
_('%s ago') % time_ago_in_words(role.updated_at)
|
7
21
|
end
|
8
22
|
end
|
9
23
|
end
|
@@ -11,9 +11,10 @@ module ForemanAnsible
|
|
11
11
|
def host_title_actions_with_run_ansible_roles(*args)
|
12
12
|
button = link_to(
|
13
13
|
icon_text('play', ' ' + _('Ansible roles'), :kind => 'fa'),
|
14
|
-
|
14
|
+
play_roles_host_path(:id => args.first.id),
|
15
15
|
:id => :ansible_roles_button,
|
16
|
-
:class => 'btn btn-default'
|
16
|
+
:class => 'btn btn-default'
|
17
|
+
)
|
17
18
|
title_actions(button_group(button)) if args.first.ansible_roles.present?
|
18
19
|
host_title_actions_without_run_ansible_roles(*args)
|
19
20
|
end
|
@@ -21,7 +22,7 @@ module ForemanAnsible
|
|
21
22
|
def multiple_actions_with_run_ansible_roles
|
22
23
|
multiple_actions_without_run_ansible_roles +
|
23
24
|
[[_('Play Ansible roles'),
|
24
|
-
|
25
|
+
multiple_play_roles_hosts_path,
|
25
26
|
false]]
|
26
27
|
end
|
27
28
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Actions
|
2
|
+
module ForemanAnsible
|
3
|
+
# Actions that initiaztes the playbook run for roles assigned to
|
4
|
+
# the host. It doest that either locally or via a proxy when available.
|
5
|
+
class PlayHostRoles < Actions::EntryAction
|
6
|
+
include ::Actions::Helpers::WithContinuousOutput
|
7
|
+
include ::Actions::Helpers::WithDelegatedAction
|
8
|
+
|
9
|
+
def plan(host, proxy_selector = ::ForemanAnsible::ProxySelector.new)
|
10
|
+
input[:host] = { :id => host.id, :name => host.fqdn }
|
11
|
+
proxy = proxy_selector.determine_proxy(host)
|
12
|
+
inventory_creator = ::ForemanAnsible::InventoryCreator.new([host])
|
13
|
+
role_names = host.all_ansible_roles.map(&:name)
|
14
|
+
playbook_creator = ::ForemanAnsible::PlaybookCreator.new(role_names)
|
15
|
+
plan_delegated_action(proxy, ::ForemanAnsibleCore::Actions::RunPlaybook,
|
16
|
+
:inventory => inventory_creator.to_hash.to_json,
|
17
|
+
:playbook => playbook_creator.roles_playbook)
|
18
|
+
plan_self
|
19
|
+
end
|
20
|
+
|
21
|
+
def finalize
|
22
|
+
if delegated_output[:exit_status].to_s != '0'
|
23
|
+
error! _('Playbook execution failed')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def rescue_strategy
|
28
|
+
::Dynflow::Action::Rescue::Fail
|
29
|
+
end
|
30
|
+
|
31
|
+
def humanized_input
|
32
|
+
_('on host %{name}') % { :name => input.fetch(:host, {})[:name] }
|
33
|
+
end
|
34
|
+
|
35
|
+
def humanized_name
|
36
|
+
_('Play Ansible roles')
|
37
|
+
end
|
38
|
+
|
39
|
+
def humanized_output
|
40
|
+
continuous_output.humanize
|
41
|
+
end
|
42
|
+
|
43
|
+
def continuous_output_providers
|
44
|
+
super << self
|
45
|
+
end
|
46
|
+
|
47
|
+
def fill_continuous_output(continuous_output)
|
48
|
+
delegated_output.fetch('result', []).each do |raw_output|
|
49
|
+
continuous_output.add_raw_output(raw_output)
|
50
|
+
end
|
51
|
+
rescue => e
|
52
|
+
continuous_output.add_exception(_('Error loading data from proxy'), e)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Actions
|
2
|
+
module ForemanAnsible
|
3
|
+
# Bulk action for running ansible roles
|
4
|
+
class PlayHostsRoles < Actions::ActionWithSubPlans
|
5
|
+
def plan(hosts)
|
6
|
+
plan_self(:host_ids => hosts.map(&:id))
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_sub_plans
|
10
|
+
proxy_selector = ::ForemanAnsible::ProxySelector.new
|
11
|
+
input[:host_ids].map do |host_id|
|
12
|
+
host = Host.find(host_id)
|
13
|
+
trigger(PlayHostRoles, host, proxy_selector)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def rescue_strategy
|
18
|
+
::Dynflow::Action::Rescue::Fail
|
19
|
+
end
|
20
|
+
|
21
|
+
def humanized_name
|
22
|
+
_('Bulk play Ansible roles')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module ProxyAPI
|
2
|
+
# ProxyAPI for Ansible
|
3
|
+
class Ansible < ::ProxyAPI::Resource
|
4
|
+
def initialize(args)
|
5
|
+
@url = args[:url] + '/ansible/'
|
6
|
+
super args
|
7
|
+
end
|
8
|
+
|
9
|
+
PROXY_ERRORS = [
|
10
|
+
Errno::ECONNREFUSED,
|
11
|
+
SocketError,
|
12
|
+
Timeout::Error,
|
13
|
+
Errno::EINVAL,
|
14
|
+
Errno::ECONNRESET,
|
15
|
+
EOFError,
|
16
|
+
Net::HTTPBadResponse,
|
17
|
+
Net::HTTPHeaderSyntaxError,
|
18
|
+
Net::ProtocolError,
|
19
|
+
RestClient::ResourceNotFound
|
20
|
+
].freeze
|
21
|
+
|
22
|
+
def roles
|
23
|
+
parse(get('roles'))
|
24
|
+
rescue *PROXY_ERRORS => e
|
25
|
+
raise ProxyException.new(url, e, N_('Unable to get roles from Ansible'))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/app/models/ansible_role.rb
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
# Simple model to store basic info about the Ansible role
|
2
2
|
class AnsibleRole < ActiveRecord::Base
|
3
|
+
include Authorizable
|
4
|
+
|
5
|
+
self.include_root_in_json = false
|
3
6
|
validates :name, :presence => true, :uniqueness => true
|
4
7
|
has_many :host_ansible_roles
|
5
8
|
has_many_hosts :through => :host_ansible_roles, :dependent => :destroy
|
9
|
+
has_many :hostgroup_ansible_roles
|
10
|
+
has_many :hostgroups, :through => :hostgroup_ansible_roles,
|
11
|
+
:dependent => :destroy
|
12
|
+
|
13
|
+
scoped_search :on => :name, :complete_value => true
|
6
14
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ForemanAnsible
|
2
|
+
# Define common behaviors between models that have many Ansible roles,
|
3
|
+
# currently Host and Hostgroup. Takes care of inheritance, etc...
|
4
|
+
module HasManyAnsibleRoles
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
def all_ansible_roles
|
9
|
+
(ansible_roles + inherited_ansible_roles).uniq
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -7,8 +7,12 @@ module ForemanAnsible
|
|
7
7
|
has_many :host_ansible_roles, :foreign_key => :host_id
|
8
8
|
has_many :ansible_roles, :through => :host_ansible_roles,
|
9
9
|
:dependent => :destroy
|
10
|
+
include ForemanAnsible::HasManyAnsibleRoles
|
10
11
|
|
11
|
-
|
12
|
+
def inherited_ansible_roles
|
13
|
+
return [] unless hostgroup
|
14
|
+
hostgroup.all_ansible_roles
|
15
|
+
end
|
12
16
|
end
|
13
17
|
end
|
14
18
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ForemanAnsible
|
2
|
+
# Relations to make Hostgroup 'have' ansible roles
|
3
|
+
module HostgroupExtensions
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
has_many :hostgroup_ansible_roles, :foreign_key => :hostgroup_id
|
8
|
+
has_many :ansible_roles, :through => :hostgroup_ansible_roles,
|
9
|
+
:dependent => :destroy
|
10
|
+
include ForemanAnsible::HasManyAnsibleRoles
|
11
|
+
|
12
|
+
def inherited_ansible_roles
|
13
|
+
ancestors.reduce([]) do |roles, hostgroup|
|
14
|
+
roles + hostgroup.ansible_roles
|
15
|
+
end.uniq
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|