foreman_acd 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/foreman_acd/ansible_playbooks_controller.rb +122 -0
- data/app/controllers/foreman_acd/api/v2/ansible_playbooks_controller.rb +54 -0
- data/app/controllers/foreman_acd/api/v2/app_instances_controller.rb +54 -0
- data/app/controllers/foreman_acd/api/v2/app_playbooks_controller.rb +0 -0
- data/app/controllers/foreman_acd/app_definitions_controller.rb +7 -4
- data/app/controllers/foreman_acd/app_instances_controller.rb +33 -126
- data/app/controllers/foreman_acd/concerns/ansible_playbook_parameters.rb +23 -0
- data/app/controllers/foreman_acd/concerns/app_definition_parameters.rb +1 -1
- data/app/controllers/foreman_acd/concerns/app_instance_parameters.rb +1 -1
- data/app/controllers/ui_acd_controller.rb +11 -3
- data/app/models/foreman_acd/ansible_playbook.rb +50 -0
- data/app/models/foreman_acd/app_definition.rb +2 -0
- data/app/models/foreman_acd/app_instance.rb +7 -0
- data/app/services/foreman_acd/app_configurator.rb +70 -0
- data/app/services/foreman_acd/app_deployer.rb +143 -0
- data/app/services/foreman_acd/inventory_creator.rb +67 -0
- data/app/views/foreman_acd/ansible_playbooks/_form.html.erb +21 -0
- data/app/views/foreman_acd/ansible_playbooks/edit.html.erb +3 -0
- data/app/views/foreman_acd/ansible_playbooks/index.html.erb +30 -0
- data/app/views/foreman_acd/ansible_playbooks/new.html.erb +3 -0
- data/app/views/foreman_acd/api/v2/ansible_playbooks/base.json.rabl +3 -0
- data/app/views/foreman_acd/api/v2/ansible_playbooks/index.json.rabl +3 -0
- data/app/views/foreman_acd/api/v2/ansible_playbooks/show.json.rabl +3 -0
- data/app/views/foreman_acd/api/v2/app_definitions/base.json.rabl +3 -0
- data/app/views/foreman_acd/api/v2/app_definitions/index.json.rabl +3 -0
- data/app/views/foreman_acd/api/v2/app_definitions/show.json.rabl +3 -0
- data/app/views/foreman_acd/api/v2/app_instances/base.json.rabl +3 -0
- data/app/views/foreman_acd/api/v2/app_instances/index.json.rabl +3 -0
- data/app/views/foreman_acd/api/v2/app_instances/show.json.rabl +3 -0
- data/app/views/foreman_acd/app_definitions/_form.html.erb +24 -10
- data/app/views/foreman_acd/app_definitions/edit.html.erb +5 -0
- data/app/views/foreman_acd/app_instances/_form.html.erb +7 -5
- data/app/views/foreman_acd/app_instances/index.html.erb +5 -1
- data/app/views/templates/job/run_acd_ansible_playbook.erb +49 -0
- data/app/views/ui_acd/ansible_data.json.rabl +6 -0
- data/app/views/ui_acd/app.json.rabl +6 -2
- data/app/views/ui_acd/app_definition.json.rabl +1 -1
- data/app/views/ui_acd/{fdata.json.rabl → foreman_data.json.rabl} +1 -1
- data/config/routes.rb +24 -1
- data/db/migrate/20200916091018_create_ansible_playbooks.rb +20 -0
- data/db/migrate/20200917120220_add_ansible_playbook_id.rb +14 -0
- data/db/migrate/20201016002819_add_ansible_vars_all_to_app_definitions.rb +5 -0
- data/db/migrate/20201016104338_add_ansible_vars_all_to_app_instances.rb +5 -0
- data/db/seeds.d/75-job_templates.rb +8 -0
- data/lib/foreman_acd/engine.rb +3 -0
- data/lib/foreman_acd/plugin.rb +53 -2
- data/lib/foreman_acd/version.rb +1 -1
- data/package.json +1 -1
- data/webpack/components/ApplicationDefinition/ApplicationDefinition.js +137 -22
- data/webpack/components/ApplicationDefinition/ApplicationDefinitionActions.js +95 -11
- data/webpack/components/ApplicationDefinition/ApplicationDefinitionConstants.js +7 -2
- data/webpack/components/ApplicationDefinition/ApplicationDefinitionHelper.js +26 -0
- data/webpack/components/ApplicationDefinition/ApplicationDefinitionReducer.js +117 -21
- data/webpack/components/ApplicationDefinition/ApplicationDefinitionSelectors.js +2 -0
- data/webpack/components/ApplicationDefinition/components/AnsiblePlaybookSelector.js +49 -0
- data/webpack/components/ApplicationDefinition/index.js +4 -0
- data/webpack/components/ApplicationInstance/ApplicationInstance.js +92 -22
- data/webpack/components/ApplicationInstance/ApplicationInstanceActions.js +37 -8
- data/webpack/components/ApplicationInstance/ApplicationInstanceConstants.js +4 -2
- data/webpack/components/ApplicationInstance/ApplicationInstanceReducer.js +98 -26
- data/webpack/components/ApplicationInstance/ApplicationInstanceSelectors.js +2 -1
- data/webpack/components/ApplicationInstance/index.js +2 -0
- data/webpack/components/ParameterSelection/ParameterSelection.js +46 -37
- data/webpack/components/ParameterSelection/ParameterSelectionActions.js +49 -52
- data/webpack/components/ParameterSelection/ParameterSelectionConstants.js +5 -3
- data/webpack/components/ParameterSelection/ParameterSelectionHelper.js +0 -32
- data/webpack/components/ParameterSelection/ParameterSelectionReducer.js +32 -16
- data/webpack/components/ParameterSelection/ParameterSelectionSelectors.js +2 -2
- data/webpack/components/ParameterSelection/index.js +4 -4
- data/webpack/components/common/DeleteTableEntry.js +1 -1
- data/webpack/reducer.js +14 -11
- metadata +48 -3
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanAcd
|
4
|
+
module Concerns
|
5
|
+
# Parameters for AnsiblePlaybooks
|
6
|
+
module AnsiblePlaybookParameters
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
class_methods do
|
10
|
+
def ansible_playbook_params_filter
|
11
|
+
Foreman::ParameterFilter.new(::ForemanAcd::AnsiblePlaybook).tap do |filter|
|
12
|
+
filter.permit(:name, :description, :scm_type, :path, :playfile)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def ansible_playbook_params
|
18
|
+
param_name = parameter_filter_context.api? ? 'ansible_playbook' : 'foreman_acd_ansible_playbook'
|
19
|
+
self.class.ansible_playbook_params_filter.filter_params(params, parameter_filter_context, param_name)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -9,7 +9,7 @@ module ForemanAcd
|
|
9
9
|
class_methods do
|
10
10
|
def app_definition_params_filter
|
11
11
|
Foreman::ParameterFilter.new(::ForemanAcd::AppDefinition).tap do |filter|
|
12
|
-
filter.permit(:name, :description, :services)
|
12
|
+
filter.permit(:name, :description, :acd_ansible_playbook_id, :services, :ansible_vars_all)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -9,7 +9,7 @@ module ForemanAcd
|
|
9
9
|
class_methods do
|
10
10
|
def app_instance_params_filter
|
11
11
|
Foreman::ParameterFilter.new(::ForemanAcd::AppInstance).tap do |filter|
|
12
|
-
filter.permit(:name, :app_definition_id, :description, :hosts)
|
12
|
+
filter.permit(:name, :app_definition_id, :description, :hosts, :ansible_vars_all)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -8,13 +8,17 @@ class UiAcdController < ::Api::V2::BaseController
|
|
8
8
|
@app_data['app_definition'] = app_definition
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
12
|
-
@
|
11
|
+
def foreman_data
|
12
|
+
@foreman_data = collect_foreman_data(params['id'])
|
13
|
+
end
|
14
|
+
|
15
|
+
def ansible_data
|
16
|
+
@ansible_data = collect_ansible_data(params['id'])
|
13
17
|
end
|
14
18
|
|
15
19
|
private
|
16
20
|
|
17
|
-
def
|
21
|
+
def collect_foreman_data(hostgroup_id)
|
18
22
|
hg = Hostgroup.find(hostgroup_id)
|
19
23
|
fdata = OpenStruct.new(
|
20
24
|
:environments => Environment.all,
|
@@ -26,4 +30,8 @@ class UiAcdController < ::Api::V2::BaseController
|
|
26
30
|
)
|
27
31
|
fdata
|
28
32
|
end
|
33
|
+
|
34
|
+
def collect_ansible_data(playbook_id)
|
35
|
+
ForemanAcd::AnsiblePlaybook.find(playbook_id).as_unified_structobj
|
36
|
+
end
|
29
37
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanAcd
|
4
|
+
# Ansible playbook
|
5
|
+
class AnsiblePlaybook < ApplicationRecord
|
6
|
+
include Authorizable
|
7
|
+
extend FriendlyId
|
8
|
+
friendly_id :name
|
9
|
+
|
10
|
+
self.table_name = 'acd_ansible_playbooks'
|
11
|
+
has_many :app_definitions, :inverse_of => :ansible_playbook, :dependent => :destroy
|
12
|
+
validates :name, :presence => true, :uniqueness => true
|
13
|
+
scoped_search :on => :name
|
14
|
+
default_scope -> { order("acd_ansible_playbooks.name") }
|
15
|
+
|
16
|
+
def self.humanize_class_name(_name = nil)
|
17
|
+
_('Ansible playbook')
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.permission_name
|
21
|
+
'ansible_playbooks'
|
22
|
+
end
|
23
|
+
|
24
|
+
def content
|
25
|
+
case scm_type
|
26
|
+
when 'directory'
|
27
|
+
File.read(File.join(path, playfile))
|
28
|
+
else
|
29
|
+
raise NotImplementedError.new "scm_type #{scm_type.inspect} not supported!"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def as_unified_structobj
|
34
|
+
groups = []
|
35
|
+
|
36
|
+
JSON.load(self.vars).each do |group_name, vars|
|
37
|
+
groups << OpenStruct.new(
|
38
|
+
:name => group_name,
|
39
|
+
:vars => vars.map { |k,v| OpenStruct.new(:name => k, :value => v) })
|
40
|
+
end
|
41
|
+
|
42
|
+
adata = OpenStruct.new(
|
43
|
+
:id => self.id,
|
44
|
+
:name => self.name,
|
45
|
+
:groups => JSON.load(self.vars)
|
46
|
+
)
|
47
|
+
adata
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -9,7 +9,9 @@ module ForemanAcd
|
|
9
9
|
|
10
10
|
validates :name, :presence => true, :uniqueness => true
|
11
11
|
has_many :app_instances, :inverse_of => :app_definition, :dependent => :destroy
|
12
|
+
belongs_to :ansible_playbook, :inverse_of => :app_definitions, :foreign_key => :acd_ansible_playbook_id
|
12
13
|
scoped_search :on => :name
|
14
|
+
default_scope -> { order("app_definitions.name") }
|
13
15
|
|
14
16
|
def self.humanize_class_name(_name = nil)
|
15
17
|
_('App Definition')
|
@@ -9,6 +9,7 @@ module ForemanAcd
|
|
9
9
|
validates :name, :presence => true, :uniqueness => true
|
10
10
|
belongs_to :app_definition, :inverse_of => :app_instances
|
11
11
|
scoped_search :on => :name
|
12
|
+
default_scope -> { order("app_instances.name") }
|
12
13
|
|
13
14
|
def self.humanize_class_name(_name = nil)
|
14
15
|
_('App Instance')
|
@@ -17,5 +18,11 @@ module ForemanAcd
|
|
17
18
|
def self.permission_name
|
18
19
|
'app_instances'
|
19
20
|
end
|
21
|
+
|
22
|
+
def foreman_hosts
|
23
|
+
app_hosts = JSON.parse(self.hosts)
|
24
|
+
host_ids = app_hosts.select{ |h| h&.key?('foreman_host_id') }.map{ |h| h['foreman_host_id'] }
|
25
|
+
::Host.find(host_ids)
|
26
|
+
end
|
20
27
|
end
|
21
28
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanAcd
|
4
|
+
# application instances configurator
|
5
|
+
class AppConfigurator
|
6
|
+
|
7
|
+
delegate :logger, :to => :Rails
|
8
|
+
|
9
|
+
def initialize(app_instance)
|
10
|
+
@app_instance = app_instance
|
11
|
+
end
|
12
|
+
|
13
|
+
def configure
|
14
|
+
job_input = {}
|
15
|
+
job_input['application_name'] = @app_instance.name
|
16
|
+
job_input['playbook_name'] = @app_instance.app_definition.ansible_playbook.name
|
17
|
+
job_input['playbook_path'] = File.join(@app_instance.app_definition.ansible_playbook.path,
|
18
|
+
@app_instance.app_definition.ansible_playbook.playfile)
|
19
|
+
|
20
|
+
# TODO should or do we really need it to a file?
|
21
|
+
#inventory_file = File.new("/tmp/acd_inventory_file", "w") # we can also use Tempfile.new() but a tempfile will be deleted soon (after transaction finished)
|
22
|
+
#inventory_file << inventory.to_yaml
|
23
|
+
#inventory_file.close
|
24
|
+
|
25
|
+
logger.info("Use inventory to configure #{@app_instance.name} with ansible playbook #{@app_instance.app_definition.ansible_playbook.name}")
|
26
|
+
|
27
|
+
begin
|
28
|
+
proxy_hosts = {}
|
29
|
+
jobs = []
|
30
|
+
|
31
|
+
hosts = @app_instance.foreman_hosts
|
32
|
+
proxy_selector = RemoteExecutionProxySelector.new
|
33
|
+
hosts.each do |h|
|
34
|
+
proxy = proxy_selector.determine_proxy(h, 'SSH')
|
35
|
+
unless proxy_hosts.has_key?(proxy.name)
|
36
|
+
proxy_hosts[proxy.name] = Array.new
|
37
|
+
end
|
38
|
+
proxy_hosts[proxy.name] << h.id
|
39
|
+
end
|
40
|
+
|
41
|
+
# TODO just for testing...
|
42
|
+
#proxy_hosts = { Host.first.name => [ Host.first.id] }
|
43
|
+
|
44
|
+
# we need to compose multiple jobs. for each proxy one job.
|
45
|
+
proxy_hosts.each do |proxy_name, host_names|
|
46
|
+
# create the inventory file
|
47
|
+
inventory = ForemanAcd::InventoryCreator.new(@app_instance, host_names).create_inventory
|
48
|
+
job_input['inventory'] = YAML.dump(inventory)
|
49
|
+
|
50
|
+
# Unfortunately, we can not use "JobInvocationComposer.for_feature" method
|
51
|
+
# because then its not possible to the set effective_user
|
52
|
+
job = JobTemplate.find(RemoteExecutionFeature.feature('run_acd_ansible_playbook').job_template_id)
|
53
|
+
params = {
|
54
|
+
:job_category => job.job_category,
|
55
|
+
:job_template_id => job.id,
|
56
|
+
:targeting_type => 'static_query',
|
57
|
+
:search_query => "name = #{proxy_name}",
|
58
|
+
:effective_user => 'foreman-proxy',
|
59
|
+
:inputs => job_input.to_hash
|
60
|
+
}
|
61
|
+
composer = JobInvocationComposer.from_api_params(params)
|
62
|
+
jobs << composer
|
63
|
+
end
|
64
|
+
rescue StandardError => e
|
65
|
+
logger.error("Failed to configure hosts: #{e.class}: #{e.message}\n#{e.backtrace.join($INPUT_RECORD_SEPARATOR)}")
|
66
|
+
end
|
67
|
+
jobs
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanAcd
|
4
|
+
# application instances deployer
|
5
|
+
class AppDeployer
|
6
|
+
|
7
|
+
delegate :logger, :to => :Rails
|
8
|
+
attr_reader :deploy_hosts
|
9
|
+
|
10
|
+
def initialize(app_instance)
|
11
|
+
@app_instance = app_instance
|
12
|
+
@deploy_hosts = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def deploy
|
16
|
+
services = JSON.parse(@app_instance.app_definition.services)
|
17
|
+
app_hosts = JSON.parse(@app_instance.hosts)
|
18
|
+
|
19
|
+
app_hosts.each do |host_data|
|
20
|
+
begin
|
21
|
+
service_data = services.select { |k| k['id'] == host_data['service'].to_i }.first
|
22
|
+
host_params = set_host_params(host_data, service_data)
|
23
|
+
|
24
|
+
host = nil
|
25
|
+
if host_data.has_key?('foreman_host_id')
|
26
|
+
logger.debug("Try to find host with id #{host_data['foreman_host_id']}")
|
27
|
+
begin
|
28
|
+
host = Host.find(host_data['foreman_host_id'])
|
29
|
+
rescue ActiveRecord::RecordNotFound
|
30
|
+
logger.info("Host with id #{host_data['foreman_host_id']} couldn\'t be found, create a new one!")
|
31
|
+
host = nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
if host.nil?
|
36
|
+
params = host_attributes(host_params)
|
37
|
+
logger.info("Host creation parameters for #{host_data['hostname']}:\n#{params}\n")
|
38
|
+
host = Host.new(params)
|
39
|
+
else
|
40
|
+
logger.info("Update parameters and re-deploy host #{host_data['hostname']}")
|
41
|
+
host.attributes = host_attributes(host_params, host)
|
42
|
+
host.setBuild
|
43
|
+
host.power.reset
|
44
|
+
end
|
45
|
+
|
46
|
+
# REMOVE ME (but very nice for testing)
|
47
|
+
#host.mac = "00:11:22:33:44:55"
|
48
|
+
|
49
|
+
apply_compute_profile(host)
|
50
|
+
host.suggest_default_pxe_loader
|
51
|
+
host.save
|
52
|
+
|
53
|
+
# save the foreman host id
|
54
|
+
host_data['foreman_host_id'] = host.id
|
55
|
+
|
56
|
+
@deploy_hosts.push({ id: host.id, name: host_data['hostname'], hostname: host.hostname, hostUrl: host_path(h), progress_report_id: host.progress_report_id})
|
57
|
+
rescue StandardError => e
|
58
|
+
logger.error("Failed to initiate host creation: #{e.class}: #{e.message}\n#{e.backtrace.join($INPUT_RECORD_SEPARATOR)}")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
return app_hosts
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
# Copied from foreman/app/controllers/api/v2/hosts_controller.rb
|
68
|
+
def apply_compute_profile(host)
|
69
|
+
host.apply_compute_profile(InterfaceMerge.new(:merge_compute_attributes => true))
|
70
|
+
host.apply_compute_profile(ComputeAttributeMerge.new)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Copied from foreman/app/controllers/api/v2/hosts_controller.rb
|
74
|
+
def host_attributes(params, host = nil)
|
75
|
+
return {} if params.nil?
|
76
|
+
|
77
|
+
params = params.deep_clone
|
78
|
+
if params[:interfaces_attributes]
|
79
|
+
# handle both hash and array styles of nested attributes
|
80
|
+
params[:interfaces_attributes] = params[:interfaces_attributes].values if params[:interfaces_attributes].is_a?(Hash) || params[:interfaces_attributes].is_a?(ActionController::Parameters)
|
81
|
+
# map interface types
|
82
|
+
params[:interfaces_attributes] = params[:interfaces_attributes].map do |nic_attr|
|
83
|
+
interface_attributes(nic_attr, :allow_nil_type => host.nil?)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
params = host.apply_inherited_attributes(params) if host
|
87
|
+
params
|
88
|
+
end
|
89
|
+
|
90
|
+
# Copied from foreman/app/controllers/api/v2/hosts_controller.rb
|
91
|
+
def interface_attributes(params, allow_nil_type: false)
|
92
|
+
params[:type] = InterfaceTypeMapper.map(params[:type]) if params.key?(:type) || allow_nil_type
|
93
|
+
params
|
94
|
+
end
|
95
|
+
|
96
|
+
def hardcoded_params
|
97
|
+
result = {}
|
98
|
+
result['managed'] = true
|
99
|
+
result['enabled'] = true
|
100
|
+
result['build'] = true
|
101
|
+
result['compute_attributes'] = { 'start' => '1' }
|
102
|
+
result['host_parameters_attributes'] = []
|
103
|
+
result
|
104
|
+
end
|
105
|
+
|
106
|
+
def set_host_params(host_data, service_data)
|
107
|
+
result = hardcoded_params
|
108
|
+
result['name'] = host_data['hostname']
|
109
|
+
result['hostgroup_id'] = service_data['hostgroup']
|
110
|
+
|
111
|
+
host_data['foremanParameters'].each do |param|
|
112
|
+
case param['type']
|
113
|
+
|
114
|
+
when 'computeprofile'
|
115
|
+
result['compute_profile_id'] = param['value']
|
116
|
+
|
117
|
+
when 'domain'
|
118
|
+
result['domain_id'] = param['value']
|
119
|
+
|
120
|
+
when 'hostparam'
|
121
|
+
result['host_parameters_attributes'].push(:name => param['name'], :value => param['value'])
|
122
|
+
|
123
|
+
when 'ip'
|
124
|
+
result['ip'] = param['value']
|
125
|
+
|
126
|
+
when 'lifecycleenv'
|
127
|
+
result['content_facet_attributes'] = { 'lifecycle_environment_id' => param['value'] }
|
128
|
+
|
129
|
+
when 'ptable'
|
130
|
+
result['ptable_id'] = param['value']
|
131
|
+
|
132
|
+
when 'puppetenv'
|
133
|
+
result['environment_id'] = param['value']
|
134
|
+
|
135
|
+
when 'password'
|
136
|
+
result['root_pass'] = param['value']
|
137
|
+
|
138
|
+
end
|
139
|
+
end
|
140
|
+
result
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanAcd
|
4
|
+
# inventory creator for application instances
|
5
|
+
class InventoryCreator
|
6
|
+
|
7
|
+
delegate :logger, :to => :Rails
|
8
|
+
|
9
|
+
def initialize(app_instance, host_ids)
|
10
|
+
@app_instance = app_instance
|
11
|
+
@host_ids = host_ids
|
12
|
+
end
|
13
|
+
|
14
|
+
# TODO: this might be part of the smart proxy plugin.
|
15
|
+
def create_inventory
|
16
|
+
inventory = {}
|
17
|
+
inventory['all'] = {}
|
18
|
+
|
19
|
+
inventory['all'] = { 'vars' => inventory_all_vars } unless @app_instance.ansible_vars_all.nil? || @app_instance.ansible_vars_all.empty?
|
20
|
+
|
21
|
+
services = JSON.parse(@app_instance.app_definition.services)
|
22
|
+
app_hosts = filtered_hosts
|
23
|
+
|
24
|
+
children = {}
|
25
|
+
app_hosts.each do |host_data|
|
26
|
+
if host_data['foreman_host_id'].nil?
|
27
|
+
logger.warn "Ignore host #{host_data['hostname']} because no foreman host id could be found. Is the host not provisioned yet?"
|
28
|
+
next
|
29
|
+
end
|
30
|
+
|
31
|
+
service_id = host_data['service'].to_i
|
32
|
+
host_service = services.select { |s| s['id'] == service_id }.first
|
33
|
+
ansible_group = host_service['ansibleGroup']
|
34
|
+
|
35
|
+
unless children.has_key?(host_service['ansibleGroup'])
|
36
|
+
children[ansible_group] = { 'hosts' => {} }
|
37
|
+
end
|
38
|
+
|
39
|
+
ansible_vars = host_data['ansibleParameters'].map { |v| { v['name'] => v['value'] } }.reduce({}, :merge!)
|
40
|
+
|
41
|
+
# in case there is no ansible_user defined, set "root" as default.
|
42
|
+
unless ansible_vars.has_key?('ansible_user')
|
43
|
+
ansible_vars['ansible_user'] = 'root'
|
44
|
+
end
|
45
|
+
|
46
|
+
children[ansible_group]['hosts'][get_fqdn(host_data['foreman_host_id'])] = ansible_vars
|
47
|
+
end
|
48
|
+
inventory['all']['children'] = children
|
49
|
+
inventory
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
def inventory_all_vars
|
54
|
+
JSON.parse(@app_instance.ansible_vars_all).map do |a|
|
55
|
+
{ a['name'] => a['value'] }
|
56
|
+
end.reduce({}, :merge!)
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_fqdn(host_id)
|
60
|
+
Host.find(host_id)&.name
|
61
|
+
end
|
62
|
+
|
63
|
+
def filtered_hosts
|
64
|
+
JSON.parse(@app_instance.hosts).select{ |h| h&.key?('foreman_host_id') && @host_ids.include?(h['foreman_host_id']) }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<%= form_for @ansible_playbook, :url => (@ansible_playbook.new_record? ? ansible_playbooks_path : ansible_playbook_path(:id => @ansible_playbook.id)) do |f| %>
|
2
|
+
<%= base_errors_for @ansible_playbook %>
|
3
|
+
|
4
|
+
<ul class="nav nav-tabs" data-tabs="tabs">
|
5
|
+
<li class="active"><a href="#primary" data-toggle="tab"><%= _('Ansible playbooks') %></a></li>
|
6
|
+
</ul>
|
7
|
+
|
8
|
+
<div class="tab-content">
|
9
|
+
<div class="tab-pane active" id="primary">
|
10
|
+
<%= text_f f, :name %>
|
11
|
+
<%= text_f f, :description %>
|
12
|
+
<%= f.hidden_field :scm_type, :value => 'directory' %>
|
13
|
+
<% # TODO:
|
14
|
+
# select_f(f, :scm_type, %w[Directory GIT], :downcase, :to_s)
|
15
|
+
%>
|
16
|
+
<%= text_f f, :path %>
|
17
|
+
<%= text_f f, :playfile %>
|
18
|
+
</div>
|
19
|
+
|
20
|
+
<%= submit_or_cancel f %>
|
21
|
+
<% end %>
|