foreman_acd 0.6.0 → 0.7.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 +75 -0
- data/app/controllers/foreman_acd/app_instances_controller.rb +19 -2
- data/app/controllers/foreman_acd/concerns/ansible_playbook_parameters.rb +1 -1
- data/app/controllers/foreman_acd/remote_execution_controller.rb +37 -21
- data/app/lib/actions/foreman_acd/deploy_all_hosts.rb +12 -7
- data/app/lib/actions/foreman_acd/run_configurator.rb +10 -7
- data/app/models/concerns/foreman_acd/host_managed_extensions.rb +2 -2
- data/app/models/foreman_acd/acd_provider.rb +7 -1
- data/app/models/foreman_acd/ansible_playbook.rb +2 -1
- data/app/models/foreman_acd/app_instance.rb +1 -1
- data/app/services/foreman_acd/acd_proxy_proxy_selector.rb +17 -0
- data/app/services/foreman_acd/app_configurator.rb +59 -15
- data/app/services/foreman_acd/app_deployer.rb +8 -2
- data/app/services/foreman_acd/inventory_creator.rb +14 -0
- data/app/views/foreman_acd/ansible_playbooks/_form.html.erb +41 -7
- data/app/views/foreman_acd/app_definitions/_form.html.erb +1 -1
- data/app/views/foreman_acd/app_instances/_form.html.erb +1 -1
- data/app/views/foreman_acd/app_instances/index.html.erb +5 -3
- data/app/views/foreman_acd/app_instances/report.html.erb +1 -1
- data/app/views/templates/job/run_acd_ansible_playbook.erb +1 -1
- data/config/routes.rb +3 -0
- data/db/migrate/20210316151145_add_git_commit_to_ansible_playbooks.rb +8 -0
- data/db/migrate/20210503122809_add_git_url_to_ansible_playbooks.rb +8 -0
- data/db/seeds.d/75-job_templates.rb +1 -1
- data/lib/foreman_acd.rb +12 -0
- data/lib/foreman_acd/engine.rb +26 -4
- data/lib/foreman_acd/plugin.rb +0 -9
- data/lib/foreman_acd/version.rb +1 -1
- data/lib/tasks/foreman_acd_tasks.rake +0 -12
- data/package.json +8 -8
- data/test/controllers/ansible_playbooks_controller_test.rb +1 -1
- data/test/controllers/app_instances_controller_test.rb +8 -3
- data/test/controllers/ui_acd_controller_test.rb +22 -6
- data/test/factories/foreman_acd_factories.rb +18 -4
- data/test/models/acd_provider_test.rb +37 -0
- data/test/models/ansible_playbook_test.rb +11 -0
- data/test/models/app_definition_test.rb +1 -1
- data/test/models/app_instance_test.rb +2 -0
- data/test/models/concerns/host_extensions_test.rb +26 -0
- data/test/models/foreman_host_test.rb +12 -0
- data/webpack/__mocks__/foremanReact/API.js +2 -0
- data/webpack/__mocks__/foremanReact/common/I18n.js +3 -0
- data/webpack/__mocks__/foremanReact/common/helpers.js +2 -0
- data/webpack/__mocks__/foremanReact/components/ForemanModal.js +7 -0
- data/webpack/__mocks__/foremanReact/components/common/forms/CommonForm.js +2 -0
- data/webpack/__mocks__/foremanReact/components/common/forms/TextInput.js +2 -0
- data/webpack/__mocks__/foremanReact/components/hosts/powerStatus.js +1 -0
- data/webpack/__snapshots__/helper.test.js.snap +14 -0
- data/webpack/components/ApplicationDefinition/ApplicationDefinition.js +1 -1
- data/webpack/components/ApplicationDefinition/__fixtures__/applicationDefinitionConfData_1.fixtures.js +288 -0
- data/webpack/components/ApplicationDefinition/__fixtures__/applicationDefinitionReducer.fixtures.js +79 -0
- data/webpack/components/ApplicationDefinition/__tests__/ApplicationDefinition.test.js +25 -0
- data/webpack/components/ApplicationDefinition/__tests__/ApplicationDefinitionReducer.test.js +119 -0
- data/webpack/components/ApplicationDefinition/__tests__/ApplicationDefinitionSelectors.test.js +41 -0
- data/webpack/components/ApplicationDefinition/__tests__/__snapshots__/ApplicationDefinition.test.js.snap +200 -0
- data/webpack/components/ApplicationDefinition/__tests__/__snapshots__/ApplicationDefinitionReducer.test.js.snap +3033 -0
- data/webpack/components/ApplicationDefinition/__tests__/__snapshots__/ApplicationDefinitionSelectors.test.js.snap +299 -0
- data/webpack/components/ApplicationDefinition/components/AnsiblePlaybookSelector.js +1 -0
- data/webpack/components/ApplicationDefinition/components/__tests__/AnsiblePlaybookSelector.test.js +41 -0
- data/webpack/components/ApplicationDefinition/components/__tests__/__snapshots__/AnsiblePlaybookSelector.test.js.snap +121 -0
- data/webpack/components/ApplicationInstance/ApplicationInstance.js +3 -5
- data/webpack/components/ApplicationInstance/__fixtures__/applicationInstanceConfData_1.fixtures.js +263 -0
- data/webpack/components/ApplicationInstance/__fixtures__/applicationInstanceReducer.fixtures.js +78 -0
- data/webpack/components/ApplicationInstance/__tests__/ApplicationInstance.test.js +23 -0
- data/webpack/components/ApplicationInstance/__tests__/ApplicationInstanceReducer.test.js +119 -0
- data/webpack/components/ApplicationInstance/__tests__/ApplicationInstanceSelectors.test.js +44 -0
- data/webpack/components/ApplicationInstance/__tests__/__snapshots__/ApplicationInstance.test.js.snap +209 -0
- data/webpack/components/ApplicationInstance/__tests__/__snapshots__/ApplicationInstanceReducer.test.js.snap +2719 -0
- data/webpack/components/ApplicationInstance/__tests__/__snapshots__/ApplicationInstanceSelectors.test.js.snap +276 -0
- data/webpack/components/ApplicationInstanceReport/__fixtures__/applicationInstanceReportData_1.fixtures.js +349 -0
- data/webpack/components/ApplicationInstanceReport/__fixtures__/applicationInstanceReportReducer.fixtures.js +20 -0
- data/webpack/components/ApplicationInstanceReport/__tests__/ApplicationInstanceReport.test.js +47 -0
- data/webpack/components/ApplicationInstanceReport/__tests__/ApplicationInstanceReportReducer.test.js +41 -0
- data/webpack/components/ApplicationInstanceReport/__tests__/ApplicationInstanceReportSelectors.test.js +26 -0
- data/webpack/components/ApplicationInstanceReport/__tests__/__snapshots__/ApplicationInstanceReport.test.js.snap +130 -0
- data/webpack/components/ApplicationInstanceReport/__tests__/__snapshots__/ApplicationInstanceReportReducer.test.js.snap +718 -0
- data/webpack/components/ApplicationInstanceReport/__tests__/__snapshots__/ApplicationInstanceReportSelectors.test.js.snap +347 -0
- data/webpack/components/ApplicationInstanceReport/components/__tests__/ReportViewer.test.js +24 -0
- data/webpack/components/ApplicationInstanceReport/components/__tests__/__snapshots__/ReportViewer.test.js.snap +24 -0
- data/webpack/components/ParameterSelection/ParameterSelectionReducer.js +2 -21
- data/webpack/components/ParameterSelection/__fixtures__/parameterSelectionData_1.fixtures.js +116 -84
- data/webpack/components/ParameterSelection/__fixtures__/parameterSelectionReducer.fixtures.js +10 -4
- data/webpack/components/ParameterSelection/__tests__/ParameterSelection.test.js +36 -46
- data/webpack/components/ParameterSelection/__tests__/ParameterSelectionReducer.test.js +31 -25
- data/webpack/components/ParameterSelection/__tests__/ParameterSelectionSelectors.test.js +6 -6
- data/webpack/components/ParameterSelection/__tests__/__snapshots__/ParameterSelection.test.js.snap +2 -126
- data/webpack/components/ParameterSelection/__tests__/__snapshots__/ParameterSelectionReducer.test.js.snap +1483 -872
- data/webpack/components/ParameterSelection/__tests__/__snapshots__/ParameterSelectionSelectors.test.js.snap +117 -79
- data/webpack/components/SyncGitRepo/SyncGitRepo.js +210 -0
- data/webpack/components/SyncGitRepo/SyncGitRepo.scss +1 -0
- data/webpack/components/SyncGitRepo/SyncGitRepoActions.js +124 -0
- data/webpack/components/SyncGitRepo/SyncGitRepoConstants.js +9 -0
- data/webpack/components/SyncGitRepo/SyncGitRepoReducer.js +80 -0
- data/webpack/components/SyncGitRepo/SyncGitRepoSelectors.js +6 -0
- data/webpack/components/SyncGitRepo/__fixtures__/syncGitRepoConfData_1.fixtures.js +7 -0
- data/webpack/components/SyncGitRepo/__fixtures__/syncGitRepoReducer.fixtures.js +44 -0
- data/webpack/components/SyncGitRepo/__tests__/SyncGitRepo.test.js +27 -0
- data/webpack/components/SyncGitRepo/__tests__/SyncGitRepoReducer.test.js +95 -0
- data/webpack/components/SyncGitRepo/__tests__/SyncGitRepoSelectors.test.js +32 -0
- data/webpack/components/SyncGitRepo/__tests__/__snapshots__/SyncGitRepo.test.js.snap +30 -0
- data/webpack/components/SyncGitRepo/__tests__/__snapshots__/SyncGitRepoReducer.test.js.snap +137 -0
- data/webpack/components/SyncGitRepo/__tests__/__snapshots__/SyncGitRepoSelectors.test.js.snap +13 -0
- data/webpack/components/SyncGitRepo/components/FormTextInput.js +42 -0
- data/webpack/components/SyncGitRepo/components/ScmTypeSelector.js +46 -0
- data/webpack/components/SyncGitRepo/index.js +28 -0
- data/webpack/components/common/ExtTextInput.js +43 -0
- data/webpack/components/common/__tests__/EditTableEntry.test.js +53 -0
- data/webpack/components/common/__tests__/LockTableEntry.test.js +35 -0
- data/webpack/components/common/__tests__/__snapshots__/DeleteTableEntry.test.js.snap +2 -2
- data/webpack/components/common/__tests__/__snapshots__/EditTableEntry.test.js.snap +81 -0
- data/webpack/components/common/__tests__/__snapshots__/LockTableEntry.test.js.snap +60 -0
- data/webpack/helper.js +15 -1
- data/webpack/helper.test.js +37 -0
- data/webpack/index.js +2 -0
- data/webpack/reducer.js +4 -0
- metadata +92 -11
- data/webpack/components/common/EasyHeaderFormatter.js +0 -18
- data/webpack/components/common/__tests__/__snapshots__/AddParameter.test.js.snap +0 -35
- data/webpack/components/common/__tests__/__snapshots__/DeleteParameter.test.js.snap +0 -41
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7b616c7ba21eea339af8509f618585dcd949ddead6ecdec57278a62c751e4fd2
|
|
4
|
+
data.tar.gz: 75c7d2e2c07d306dee127bc50c6b300934f90066bc4a491e49f17f65ac6b7c24
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bba62637508bbbd4e35772a55ad1126fea7a8cb3c1658c6f734b02ccf03d44048db40fa621bb51e796220668e7a49e8b03c3169a77b818f6dbbde117d09edfe2
|
|
7
|
+
data.tar.gz: a6e4ba1bb97250e8bcebe6180abcf4755859b73828febda64353b47021acadcc33fd99e2ab4b45ac965e5d643c368bbfb47aee421a80979c7a4c69354a18b297
|
|
@@ -7,6 +7,7 @@ module ForemanAcd
|
|
|
7
7
|
include ::ForemanAcd::Concerns::AnsiblePlaybookParameters
|
|
8
8
|
|
|
9
9
|
before_action :find_resource, :only => [:edit, :update, :destroy, :import_vars]
|
|
10
|
+
after_action :delete_synced_repo, :only => [:new, :edit, :create, :update, :destroy, :index]
|
|
10
11
|
|
|
11
12
|
def index
|
|
12
13
|
@ansible_playbooks = resource_base.search_for(params[:search], :order => params[:order]).paginate(:page => params[:page])
|
|
@@ -18,6 +19,11 @@ module ForemanAcd
|
|
|
18
19
|
|
|
19
20
|
def create
|
|
20
21
|
@ansible_playbook = AnsiblePlaybook.new(ansible_playbook_params)
|
|
22
|
+
if session[:git_path]
|
|
23
|
+
@ansible_playbook.update(:path => ansible_playbook_full_path(ansible_playbook_rename(@ansible_playbook[:name])))
|
|
24
|
+
FileUtils.mv(session[:git_path], @ansible_playbook[:path])
|
|
25
|
+
session[:git_path] = nil
|
|
26
|
+
end
|
|
21
27
|
if @ansible_playbook.save
|
|
22
28
|
process_success :success_msg => _("Successfully created %s. You need to press the \"Import groups\" button
|
|
23
29
|
before this ansible playbook can be used in App Definitions!") % @ansible_playbook
|
|
@@ -29,6 +35,20 @@ module ForemanAcd
|
|
|
29
35
|
def edit; end
|
|
30
36
|
|
|
31
37
|
def update
|
|
38
|
+
# Move synced repo to new path if ansible_playbook name is changed
|
|
39
|
+
if !session[:git_path].nil? && ansible_playbook_params[:name] != @ansible_playbook[:name]
|
|
40
|
+
FileUtils.mv(@ansible_playbook[:path], ansible_playbook_full_path(ansible_playbook_rename(ansible_playbook_params[:name])))
|
|
41
|
+
@ansible_playbook.update(:path => ansible_playbook_full_path(ansible_playbook_rename(ansible_playbook_params[:name])))
|
|
42
|
+
session[:git_path] = nil
|
|
43
|
+
|
|
44
|
+
# Remove old version and copy new version of synced repository
|
|
45
|
+
elsif !session[:git_path].nil? && ansible_playbook_params[:name] == @ansible_playbook.name
|
|
46
|
+
remove_ansible_dir(@ansible_playbook[:path]) if @ansible_playbook.path
|
|
47
|
+
@ansible_playbook.update(:path => ansible_playbook_full_path(ansible_playbook_rename(@ansible_playbook[:name])))
|
|
48
|
+
FileUtils.mv(session[:git_path], @ansible_playbook[:path])
|
|
49
|
+
session[:git_path] = nil
|
|
50
|
+
end
|
|
51
|
+
|
|
32
52
|
if @ansible_playbook.update(ansible_playbook_params)
|
|
33
53
|
process_success
|
|
34
54
|
else
|
|
@@ -44,10 +64,51 @@ module ForemanAcd
|
|
|
44
64
|
end
|
|
45
65
|
end
|
|
46
66
|
|
|
67
|
+
def sync_git_repo
|
|
68
|
+
@ansible_playbook = AnsiblePlaybook.new
|
|
69
|
+
sync_params = params[:ansible_playbook]
|
|
70
|
+
dir = Dir.mktmpdir
|
|
71
|
+
|
|
72
|
+
begin
|
|
73
|
+
git = Git.init(dir)
|
|
74
|
+
|
|
75
|
+
if ForemanAcd.proxy_setting.present?
|
|
76
|
+
git.config('http.proxy', ForemanAcd.proxy_setting)
|
|
77
|
+
logger.info("HTTP Proxy used: #{git.config['http.proxy']}")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
git.add_remote('origin', sync_params[:git_url])
|
|
81
|
+
git.fetch
|
|
82
|
+
git.checkout(sync_params[:git_commit])
|
|
83
|
+
|
|
84
|
+
session[:git_path] = git.dir.path
|
|
85
|
+
rescue StandardError => e
|
|
86
|
+
logger.error("Failed to sync git repository: #{e}")
|
|
87
|
+
render :json => { :status => 'error', :message => e }, :status => :internal_server_error
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Remove abandoned synced git repositories
|
|
92
|
+
def delete_synced_repo
|
|
93
|
+
names = []
|
|
94
|
+
AnsiblePlaybook.all.each do |ansible_playbook|
|
|
95
|
+
names.push(ansible_playbook_rename(ansible_playbook.name))
|
|
96
|
+
end
|
|
97
|
+
names.push('.', '..')
|
|
98
|
+
return unless Dir.exist?(ForemanAcd.ansible_playbook_path)
|
|
99
|
+
Dir.foreach(ForemanAcd.ansible_playbook_path) do |dirname|
|
|
100
|
+
next if names.include? dirname
|
|
101
|
+
remove_ansible_dir(ansible_playbook_full_path(dirname))
|
|
102
|
+
logger.info("Successfully removed #{dirname}")
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
47
106
|
def action_permission
|
|
48
107
|
case params[:action]
|
|
49
108
|
when 'import_vars'
|
|
50
109
|
:import_vars
|
|
110
|
+
when 'sync_git_repo'
|
|
111
|
+
:sync_git_repo
|
|
51
112
|
when 'grab'
|
|
52
113
|
:grab
|
|
53
114
|
else
|
|
@@ -120,5 +181,19 @@ module ForemanAcd
|
|
|
120
181
|
process_error :error_msg => _(errors.join(' ')), :redirect => ansible_playbooks_path
|
|
121
182
|
end
|
|
122
183
|
end
|
|
184
|
+
|
|
185
|
+
private
|
|
186
|
+
|
|
187
|
+
def ansible_playbook_rename(name)
|
|
188
|
+
name.split(/\W+/).join('_')
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def remove_ansible_dir(dirpath)
|
|
192
|
+
FileUtils.remove_dir(dirpath) if Dir.exist?(dirpath)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def ansible_playbook_full_path(dirname)
|
|
196
|
+
File.join(ForemanAcd.ansible_playbook_path, dirname)
|
|
197
|
+
end
|
|
123
198
|
end
|
|
124
199
|
end
|
|
@@ -72,10 +72,12 @@ module ForemanAcd
|
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
def deploy
|
|
75
|
+
value = false
|
|
75
76
|
@app_instance.clean_all_hosts if params[:delete_hosts]
|
|
76
|
-
|
|
77
|
+
value = safe_deploy? if params[:safe_deploy]
|
|
78
|
+
session.delete(:remember_hosts)
|
|
77
79
|
logger.info('Run async foreman task to deploy hosts')
|
|
78
|
-
async_task = ForemanTasks.async_task(::Actions::ForemanAcd::DeployAllHosts, @app_instance)
|
|
80
|
+
async_task = ForemanTasks.async_task(::Actions::ForemanAcd::DeployAllHosts, @app_instance, value)
|
|
79
81
|
@app_instance.update!(:last_deploy_task => async_task)
|
|
80
82
|
process_success(:success_msg => _('Started task to deploy hosts for %s') % @app_instance)
|
|
81
83
|
rescue StandardError => e
|
|
@@ -84,6 +86,11 @@ module ForemanAcd
|
|
|
84
86
|
process_error :error_msg => error_msg
|
|
85
87
|
end
|
|
86
88
|
|
|
89
|
+
def safe_deploy?
|
|
90
|
+
return false if session[:remember_hosts].empty?
|
|
91
|
+
session[:remember_hosts]
|
|
92
|
+
end
|
|
93
|
+
|
|
87
94
|
def report
|
|
88
95
|
@report_hosts = collect_host_report_data
|
|
89
96
|
logger.debug("app instance host details: #{@report_hosts.inspect}")
|
|
@@ -91,14 +98,24 @@ module ForemanAcd
|
|
|
91
98
|
|
|
92
99
|
def app_instance_has_foreman_hosts
|
|
93
100
|
hosts = JSON.parse(@app_instance.hosts)
|
|
101
|
+
session[:remember_hosts] = []
|
|
94
102
|
hosts.each do |h|
|
|
95
103
|
if @app_instance.foreman_hosts.where(:hostname => h['hostname']).exists?
|
|
104
|
+
old_host = @app_instance.foreman_hosts.find_by(:hostname => h['hostname'])
|
|
105
|
+
|
|
96
106
|
@app_instance.foreman_hosts.where(:hostname => h['hostname']).
|
|
97
107
|
update(:service => h['service'], :description => h['description'],
|
|
98
108
|
:foremanParameters => JSON.dump(h['foremanParameters']), :ansibleParameters => JSON.dump(h['ansibleParameters']))
|
|
109
|
+
|
|
110
|
+
updated_host = @app_instance.foreman_hosts.find_by(:hostname => h['hostname'])
|
|
111
|
+
|
|
112
|
+
# Store hosts if updated for safe deploy
|
|
113
|
+
session[:remember_hosts] << updated_host.id if updated_host.updated_at != old_host.updated_at
|
|
99
114
|
else
|
|
100
115
|
@app_instance.foreman_hosts.create(:hostname => h['hostname'], :service => h['service'], :description => h['description'],
|
|
101
116
|
:foremanParameters => JSON.dump(h['foremanParameters']), :ansibleParameters => JSON.dump(h['ansibleParameters']))
|
|
117
|
+
# Store new hosts for safe deploy
|
|
118
|
+
session[:remember_hosts] << @app_instance.foreman_hosts.find_by(:hostname => h['hostname']).id
|
|
102
119
|
end
|
|
103
120
|
end
|
|
104
121
|
|
|
@@ -9,7 +9,7 @@ module ForemanAcd
|
|
|
9
9
|
class_methods do
|
|
10
10
|
def ansible_playbook_params_filter
|
|
11
11
|
Foreman::ParameterFilter.new(::ForemanAcd::AnsiblePlaybook).tap do |filter|
|
|
12
|
-
filter.permit(:name, :description, :scm_type, :path, :playfile, :location_ids => [], :organization_ids => [])
|
|
12
|
+
filter.permit(:name, :description, :scm_type, :path, :git_commit, :git_url, :playfile, :location_ids => [], :organization_ids => [])
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
end
|
|
@@ -4,25 +4,40 @@ module ForemanAcd
|
|
|
4
4
|
# Class to run remote execution jobs
|
|
5
5
|
class RemoteExecutionController < JobInvocationsController
|
|
6
6
|
def new
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
set_app_instance
|
|
8
|
+
result, job = init_configuration
|
|
9
|
+
|
|
10
|
+
if result.success == true
|
|
11
|
+
@composer = job
|
|
12
|
+
else
|
|
13
|
+
redirect_to(app_instances_path, :error => _("Coult not create remote execution job to configure the app '%{app_instance}': %{msg}") % {
|
|
14
|
+
:app_instance => @app_instance, :msg => result.error
|
|
15
|
+
})
|
|
16
|
+
end
|
|
9
17
|
end
|
|
10
18
|
|
|
11
19
|
def create
|
|
12
20
|
customize_first = params[:customize] || false
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
begin
|
|
22
|
+
set_app_instance
|
|
23
|
+
result, job = init_configuration
|
|
24
|
+
|
|
25
|
+
unless result.success == true
|
|
26
|
+
return redirect_to(app_instances_path, :error => _("Coult not create remote execution job to configure the app '%{app_instance}': %{msg}") % {
|
|
27
|
+
:app_instance => @app_instance, :msg => result.error
|
|
28
|
+
})
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
@composer = job
|
|
32
|
+
if customize_first == false
|
|
33
|
+
@composer.trigger!
|
|
34
|
+
redirect_to job_invocation_path(@composer.job_invocation)
|
|
35
|
+
else
|
|
36
|
+
# redirect to the job itself if we want to customize the job
|
|
37
|
+
render :action => 'new'
|
|
38
|
+
end
|
|
39
|
+
rescue StandardError => e
|
|
40
|
+
redirect_to app_instances_path, :error => _("#{job}, #{e}")
|
|
26
41
|
end
|
|
27
42
|
end
|
|
28
43
|
|
|
@@ -34,13 +49,14 @@ module ForemanAcd
|
|
|
34
49
|
|
|
35
50
|
private
|
|
36
51
|
|
|
37
|
-
def
|
|
38
|
-
app_instance = ForemanAcd::AppInstance.find_by(:id => params[:id])
|
|
39
|
-
|
|
52
|
+
def set_app_instance
|
|
53
|
+
@app_instance = ForemanAcd::AppInstance.find_by(:id => params[:id])
|
|
54
|
+
end
|
|
40
55
|
|
|
41
|
-
|
|
42
|
-
logger.debug("Creating
|
|
43
|
-
|
|
56
|
+
def init_configuration
|
|
57
|
+
logger.debug("Creating job to configure the app #{@app_instance}. Customize first: #{params[:customize]}")
|
|
58
|
+
app_configurator = ForemanAcd::AppConfigurator.new(@app_instance)
|
|
59
|
+
app_configurator.configure
|
|
44
60
|
end
|
|
45
61
|
end
|
|
46
62
|
end
|
|
@@ -4,27 +4,32 @@ module Actions
|
|
|
4
4
|
module ForemanAcd
|
|
5
5
|
# DeployAllHosts implements a Foreman Task EntryAction
|
|
6
6
|
class DeployAllHosts < Actions::EntryAction
|
|
7
|
-
def plan(app_instance)
|
|
8
|
-
action_subject(app_instance)
|
|
7
|
+
def plan(app_instance, safe_deploy)
|
|
8
|
+
action_subject(app_instance, :safe_deploy => safe_deploy)
|
|
9
9
|
plan_self(:id => app_instance.id)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def run
|
|
13
13
|
output[:status] = 'IN PROGRESS'
|
|
14
14
|
app_instance = ::ForemanAcd::AppInstance.find(input.fetch(:id))
|
|
15
|
+
safe_deploy = input.fetch(:safe_deploy)
|
|
15
16
|
|
|
16
|
-
# Goal: all or nothing
|
|
17
|
+
# Goal: all, safe_deploy or nothing
|
|
17
18
|
begin
|
|
18
|
-
|
|
19
|
+
if safe_deploy
|
|
20
|
+
::Foreman::Logging.logger('foreman_acd').info "Start to safe deploy hosts of the app #{app_instance}"
|
|
21
|
+
else
|
|
22
|
+
::Foreman::Logging.logger('foreman_acd').info "Start to deploy all hosts of the app #{app_instance}"
|
|
23
|
+
end
|
|
19
24
|
app_deployer = ::ForemanAcd::AppDeployer.new(app_instance)
|
|
20
|
-
output[:data] = app_deployer.deploy
|
|
25
|
+
output[:data] = app_deployer.deploy(safe_deploy)
|
|
21
26
|
output[:status] = 'SUCCESS'
|
|
22
27
|
rescue StandardError => e
|
|
23
|
-
::Foreman::Logging.logger('foreman_acd').error "Error while deploying hosts for application instance. Clean up all other hosts: #{e}"
|
|
28
|
+
::Foreman::Logging.logger('foreman_acd').error "Error while deploying hosts for application instance '#{app_instance.name}'. Clean up all other hosts: #{e}"
|
|
24
29
|
app_instance.clean_all_hosts
|
|
25
30
|
|
|
26
|
-
output[:error] = e.to_s
|
|
27
31
|
output[:status] = 'FAILURE'
|
|
32
|
+
raise "Error while deploying hosts for application instance '#{app_instance.name}': (#{e.message})"
|
|
28
33
|
end
|
|
29
34
|
end
|
|
30
35
|
|
|
@@ -15,15 +15,18 @@ module Actions
|
|
|
15
15
|
app_instance = ::ForemanAcd::AppInstance.find(input.fetch(:id))
|
|
16
16
|
app_configurator = ::ForemanAcd::AppConfigurator.new(app_instance)
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
result, job = app_configurator.configure
|
|
19
|
+
if result.success
|
|
20
|
+
::Foreman::Logging.logger('foreman_acd').info "Creating job to configure the app #{app_instance}"
|
|
21
|
+
job.trigger!
|
|
22
|
+
else
|
|
23
|
+
::Foreman::Logging.logger('foreman_acd').error "Could not create the job to configure the app #{app_instance}: #{result.error}"
|
|
24
|
+
end
|
|
23
25
|
rescue StandardError => e
|
|
24
|
-
::Foreman::Logging.logger('foreman_acd').error "Error while configuring application instance: #{e}"
|
|
25
|
-
|
|
26
|
+
::Foreman::Logging.logger('foreman_acd').error "Error while configuring application instance '#{app_instance.name}': #{e}"
|
|
27
|
+
|
|
26
28
|
output[:status] = 'FAILURE'
|
|
29
|
+
raise "Error while configuring hosts via ansible playbook for application instance '#{app_instance.name}': (#{e.message})"
|
|
27
30
|
end
|
|
28
31
|
end
|
|
29
32
|
|
|
@@ -13,13 +13,13 @@ module ForemanAcd
|
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
private
|
|
17
|
-
|
|
18
16
|
def deployed_via_acd?
|
|
19
17
|
find_app_instance_host
|
|
20
18
|
@app_instance_host.present?
|
|
21
19
|
end
|
|
22
20
|
|
|
21
|
+
private
|
|
22
|
+
|
|
23
23
|
def find_app_instance_host
|
|
24
24
|
@app_instance_host = ForemanAcd::ForemanHost.find_by(:host_id => id)
|
|
25
25
|
end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module ForemanAcd
|
|
4
4
|
# Implement a RemoteExecutionProvider
|
|
5
|
-
class AcdProvider < RemoteExecutionProvider
|
|
5
|
+
class AcdProvider < ::RemoteExecutionProvider
|
|
6
6
|
class << self
|
|
7
7
|
def supports_effective_user?
|
|
8
8
|
true
|
|
@@ -25,6 +25,12 @@ module ForemanAcd
|
|
|
25
25
|
def ssh_key_passphrase(_host); end
|
|
26
26
|
|
|
27
27
|
def sudo_password(_host); end
|
|
28
|
+
|
|
29
|
+
# Workaround till infrastructure jobs on proxies are possible. See
|
|
30
|
+
# configure in services/foreman_acd/app_configurator.rb for more details.
|
|
31
|
+
# def required_proxy_selector_for(_template)
|
|
32
|
+
# AcdProxyProxySelector.new
|
|
33
|
+
# end
|
|
28
34
|
end
|
|
29
35
|
end
|
|
30
36
|
end
|
|
@@ -12,6 +12,7 @@ module ForemanAcd
|
|
|
12
12
|
self.table_name = 'acd_ansible_playbooks'
|
|
13
13
|
has_many :app_definitions, :inverse_of => :ansible_playbook, :foreign_key => 'acd_ansible_playbook_id', :dependent => :restrict_with_error
|
|
14
14
|
validates :name, :presence => true, :uniqueness => true
|
|
15
|
+
validates :scm_type, :presence => true
|
|
15
16
|
scoped_search :on => :name
|
|
16
17
|
|
|
17
18
|
default_scope do
|
|
@@ -44,7 +45,7 @@ module ForemanAcd
|
|
|
44
45
|
|
|
45
46
|
def content
|
|
46
47
|
case scm_type
|
|
47
|
-
when 'directory'
|
|
48
|
+
when 'directory' || 'git'
|
|
48
49
|
File.read(File.join(path, playfile))
|
|
49
50
|
else
|
|
50
51
|
raise NotImplementedError.new "scm_type #{scm_type.inspect} not supported!"
|
|
@@ -54,7 +54,7 @@ module ForemanAcd
|
|
|
54
54
|
ids.each do |host_id|
|
|
55
55
|
h = ::Host.find(host_id) unless host_id.nil?
|
|
56
56
|
if h
|
|
57
|
-
Katello::RegistrationManager.unregister_host(h, :unregistering => false) if ForemanAcd
|
|
57
|
+
Katello::RegistrationManager.unregister_host(h, :unregistering => false) if ForemanAcd.with_katello?
|
|
58
58
|
h.destroy
|
|
59
59
|
end
|
|
60
60
|
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ForemanAcd
|
|
4
|
+
# AcdProxy Selector implementing a RemoteExecutionProxySelector which
|
|
5
|
+
# only returns the Smart Proxy of the given host
|
|
6
|
+
class AcdProxyProxySelector < ::RemoteExecutionProxySelector
|
|
7
|
+
def determine_proxy(*args)
|
|
8
|
+
host, _provider = args
|
|
9
|
+
|
|
10
|
+
# We already did the determine_proxy in app_configurator. We want that REX
|
|
11
|
+
# isn't doing the determination of the proxy twice.
|
|
12
|
+
# Therefore, we will just return the host, which is the proxy!
|
|
13
|
+
|
|
14
|
+
::SmartProxy.find_by(:name => host.name)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -19,12 +19,36 @@ module ForemanAcd
|
|
|
19
19
|
|
|
20
20
|
begin
|
|
21
21
|
proxy_hosts = {}
|
|
22
|
-
|
|
22
|
+
job = nil
|
|
23
|
+
result = OpenStruct.new
|
|
23
24
|
|
|
24
25
|
hosts = @app_instance.foreman_hosts
|
|
26
|
+
|
|
27
|
+
# Important: This uses the REX Proxy Selector and not
|
|
28
|
+
# the AcdProxySelection because the AcdProxySelector
|
|
29
|
+
# does not find the proxy but only return the given
|
|
30
|
+
# host. This is required because we want to run the
|
|
31
|
+
# ansible playbook for a group of hosts on the smart proxy.
|
|
32
|
+
# So the process need to be:
|
|
33
|
+
# 1. get the proxy which is required to connect to host a,b,c
|
|
34
|
+
# 2. run the job on the proxy
|
|
35
|
+
# In 2. we need to make sure that REX doesn't try to find the
|
|
36
|
+
# proxy which is necessary to connect to the proxy
|
|
25
37
|
proxy_selector = RemoteExecutionProxySelector.new
|
|
26
38
|
hosts.each do |h|
|
|
27
|
-
|
|
39
|
+
begin
|
|
40
|
+
unless h.host
|
|
41
|
+
result.success = false
|
|
42
|
+
result.error = 'App Instance is not deployed'
|
|
43
|
+
return [result, job]
|
|
44
|
+
end
|
|
45
|
+
proxy = proxy_selector.determine_proxy(h.host, 'ACD')
|
|
46
|
+
result.success = true
|
|
47
|
+
rescue NoMethodError => e
|
|
48
|
+
result.success = false
|
|
49
|
+
result.error = "#{e}, Install/Update smart-proxies for ACD"
|
|
50
|
+
return [result, job]
|
|
51
|
+
end
|
|
28
52
|
proxy_hosts[proxy.name] = [] unless proxy_hosts.key?(proxy.name)
|
|
29
53
|
proxy_hosts[proxy.name] << h
|
|
30
54
|
end
|
|
@@ -32,23 +56,43 @@ module ForemanAcd
|
|
|
32
56
|
# TODO: just for testing...
|
|
33
57
|
# proxy_hosts = { Host.first.name => [ Host.first.id] }
|
|
34
58
|
|
|
35
|
-
|
|
59
|
+
proxy_inventories = {}
|
|
60
|
+
proxy_host_ids = []
|
|
36
61
|
proxy_hosts.each do |proxy_name, foreman_hosts|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
)
|
|
46
|
-
|
|
62
|
+
proxy_inventories[proxy_name] = ForemanAcd::InventoryCreator.new(@app_instance, foreman_hosts).create_inventory
|
|
63
|
+
|
|
64
|
+
# Workaround till infrastructure jobs on proxies are possible. See
|
|
65
|
+
# https://community.theforeman.org/t/infrastructure-roles/22001/33
|
|
66
|
+
#
|
|
67
|
+
# Why do we use 'foreman_hosts.first.host'? REX is 'host-centric'. During
|
|
68
|
+
# job execution, REX will try to find the proxy on which the job should be executed.
|
|
69
|
+
# We throw the first host at REX's feet so that the resolution of the
|
|
70
|
+
# proxy works (... which we have already done above).
|
|
71
|
+
# ACD on the smart proxy side will call the ansible-playbook for ALL hosts
|
|
72
|
+
# which are behind this smart proxy.
|
|
73
|
+
#
|
|
74
|
+
# Additionally, we disable that AcdProxyProxySelector is used.
|
|
75
|
+
# See required_proxy_selector_for in models/foreman_acd/acd_provider.rb
|
|
76
|
+
proxy_host_ids << foreman_hosts.first.host.id
|
|
77
|
+
|
|
78
|
+
# Actually, we want this:
|
|
79
|
+
# proxy_host_ids << Host.find_by(:name => proxy_name).id
|
|
47
80
|
end
|
|
81
|
+
|
|
82
|
+
job_input['inventory'] = YAML.dump(proxy_inventories)
|
|
83
|
+
composer = JobInvocationComposer.for_feature(
|
|
84
|
+
:run_acd_ansible_playbook,
|
|
85
|
+
proxy_host_ids,
|
|
86
|
+
job_input.to_hash
|
|
87
|
+
)
|
|
88
|
+
job = composer
|
|
48
89
|
rescue StandardError => e
|
|
49
|
-
|
|
90
|
+
result.success = false
|
|
91
|
+
result.error = _('Failed to configure hosts: %{err_msg}' % { :err_msg => e.message })
|
|
92
|
+
logger.error('Failed to configure hosts: %{err_class}: %{err_msg}' % { :err_class => e.class, :err_msg => e.message })
|
|
93
|
+
job = nil
|
|
50
94
|
end
|
|
51
|
-
|
|
95
|
+
[result, job]
|
|
52
96
|
end
|
|
53
97
|
end
|
|
54
98
|
end
|