foreman_acd 0.3.0 → 0.4.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/README.md +79 -26
- data/app/controllers/foreman_acd/ansible_playbooks_controller.rb +5 -5
- data/app/controllers/foreman_acd/app_definitions_controller.rb +2 -1
- data/app/controllers/foreman_acd/app_instances_controller.rb +17 -39
- data/app/controllers/foreman_acd/remote_execution_controller.rb +49 -0
- data/app/models/foreman_acd/ansible_playbook.rb +1 -1
- data/app/services/foreman_acd/app_deployer.rb +1 -5
- data/app/views/foreman_acd/ansible_playbooks/index.html.erb +2 -2
- data/app/views/foreman_acd/app_instances/index.html.erb +2 -2
- data/config/routes.rb +2 -1
- data/lib/foreman_acd/version.rb +1 -1
- data/webpack/components/ApplicationDefinition/ApplicationDefinition.js +3 -3
- data/webpack/components/ApplicationDefinition/ApplicationDefinitionActions.js +3 -3
- data/webpack/components/ApplicationInstance/ApplicationInstance.js +3 -3
- data/webpack/components/ApplicationInstance/ApplicationInstanceActions.js +2 -2
- data/webpack/components/ParameterSelection/ParameterSelectionActions.js +3 -3
- data/webpack/components/common/EasyHeaderFormatter.js +18 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 433f2c68da81192db3c98fc013ed2149490f2471e84d372db8241522a33b6630
|
4
|
+
data.tar.gz: aa46c833de3feb1cce0802de82dec78f1610331984e6df8df649fdadfffa2b2a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0accbf314dd5776a5b012507d97619be98beff2c11e523da4d27f69e9fdb1bf1d284c134dba6549719312a66ede8cb80c8a06e3851f01a14951b1752ef2e29e8
|
7
|
+
data.tar.gz: d003bc7a5de1c180b2e33ade4e85b2912776db564d59ff9d8eca4f9ccc00c38591fd061649df07bb89e76ad0b0ac5efe1c64dd506132148aaf087b758a18c078
|
data/README.md
CHANGED
@@ -4,67 +4,121 @@
|
|
4
4
|
|
5
5
|
A plugin to bring an user self service portal and application centric deployment to Foreman.
|
6
6
|
|
7
|
+
|
7
8
|
# Description
|
8
9
|
|
9
|
-
The target of this plugin is, to deploy whole applications which include multiple hosts
|
10
|
-
|
10
|
+
The target of this plugin is, to deploy whole applications which include multiple hosts and
|
11
|
+
configure them using an Ansible Playbook / saltstack state.
|
11
12
|
|
12
13
|
This plugin follows the idea of different user types working together.
|
13
|
-
The administrative user creates
|
14
|
+
The administrative user creates Application Definition including multiple servers and
|
14
15
|
configuration management items (Ansible Playbook, saltstack state).
|
15
|
-
The user can create and deploy new
|
16
|
+
The user can create and deploy new Application Instaces with an easy to use self service portal.
|
16
17
|
|
17
|
-
*Example Application Definition:*
|
18
|
-
To run a complex web application, a loadbalancer is required.
|
18
|
+
*Example Application Definition:* To run a complex web application, a loadbalancer is required.
|
19
19
|
The loadbalancer routes the requests to 3 different web servers.
|
20
20
|
The web servers are using a database which is in high availability mode on 2 hosts.
|
21
21
|
=> 6 hosts are required.
|
22
22
|
|
23
23
|
This plugin aims to setup all 6 hosts and to deploy the application.
|
24
24
|
|
25
|
+
|
25
26
|
# Current State
|
26
|
-
|
27
|
-
|
27
|
+
|
28
|
+
## Application Definition
|
29
|
+
|
30
|
+
- Configure a ansible playbook
|
31
|
+
- Use the configured ansible playbook in a Application Definition
|
32
|
+
- Overwrite ansible playbook's group variables for the Application Definition
|
33
|
+
- Set foreman parameters in the Application Definition
|
34
|
+
- Setup various services like webservers, database-servers, etc.
|
35
|
+
|
36
|
+
## Application Instance
|
37
|
+
|
38
|
+
- Use an Application Definition for your Application Instance
|
39
|
+
- Configure specific hosts which uses the Application Definitions services
|
40
|
+
- Deploy these hosts
|
41
|
+
- Configure the hosts using the configured ansible playbook
|
42
|
+
|
28
43
|
|
29
44
|
# Road Map
|
30
|
-
-
|
31
|
-
- Add
|
32
|
-
- Add
|
45
|
+
-
|
46
|
+
- Add Application deployment with single host requirements
|
47
|
+
- Add Application deployment with multi host requirements
|
33
48
|
|
34
49
|
## WARNING
|
35
50
|
|
36
51
|
This plugin is in development.
|
37
|
-
In the current state, a self service portal to deploy single servers can be created.
|
38
52
|
|
39
53
|
## Installation
|
40
54
|
|
41
|
-
See [How_to_Install_a_Plugin](
|
42
|
-
for how to install Foreman plugins
|
55
|
+
See [How_to_Install_a_Plugin](https://theforeman.org/plugins/#2.Installation)
|
56
|
+
for how to install Foreman plugins.
|
57
|
+
|
58
|
+
### TL;DR:
|
59
|
+
|
60
|
+
yum install tfm-rubygem-foreman_acd
|
61
|
+
foreman-maintain service restart --only foreman
|
62
|
+
|
63
|
+
In some cases you need to do manally
|
64
|
+
|
65
|
+
foreman-rake db:migrate
|
66
|
+
foreman-rake db:seed
|
67
|
+
|
68
|
+
### Hints
|
43
69
|
|
44
|
-
|
70
|
+
Katello plugin need to exist, too.
|
71
|
+
|
72
|
+
### Configuration
|
73
|
+
|
74
|
+
To get ansible playbooks running, you need to:
|
75
|
+
|
76
|
+
cat /var/lib/foreman-proxy/ssh/id_rsa_foreman_proxy.pub >> /root/.ssh/authorized_keys
|
77
|
+
|
78
|
+
Make sure, that the job template 'Run ACD Ansible Playbook - SSH Default' is part of your organization / location.
|
45
79
|
|
46
80
|
## Usage
|
47
81
|
|
48
|
-
|
82
|
+
### Ansible Playbook
|
83
|
+
|
84
|
+
* Copy (or checkout a git repository) to e.g. /opt/ansible-playbook
|
85
|
+
* Add a new Ansible Playbook via Configure -> Ansible Playbook
|
86
|
+
* Set the path to /opt/ansible-playbook and name the playbook file. (e.g. site.yml)
|
87
|
+
* Save it and press "Import group variables" for this newly created ansible playbook.
|
88
|
+
|
89
|
+
### Application Definition (Admin)
|
90
|
+
|
49
91
|
* Create an Application Definition (Configure -> Application Definition) first
|
50
|
-
* Select the
|
92
|
+
* Select the Ansible Playbook you want to use.
|
93
|
+
* Add new services and specifiy the host group you want to use.
|
51
94
|
* Specifiy the values, a user could overwrite.
|
52
95
|
(you can set a default value, if you want)
|
53
96
|
|
54
|
-
Application Instance (User)
|
55
|
-
|
97
|
+
### Application Instance (User)
|
98
|
+
|
99
|
+
* Create an Application Instance (Configure -> Application Instance)
|
56
100
|
* Select the Application Definition which should be used
|
57
101
|
* Set the values.
|
58
102
|
Remember, all parameters need to have a value.
|
59
103
|
* Save the Application Instance
|
60
|
-
|
61
|
-
|
104
|
+
|
105
|
+
### Deploy & Configure the Application Instance (User)
|
106
|
+
|
107
|
+
* To Deploy the host, select "Deploy" in the action selection dropdown field
|
108
|
+
on the Application Instance index site.
|
109
|
+
* See if the hosts are deployed via action selection dropdown -> report.
|
110
|
+
* After all hosts are deployed, run the ansible playbook via
|
111
|
+
action selection dropdown -> Run ansible playbook
|
112
|
+
|
62
113
|
|
63
114
|
## TODO
|
64
115
|
|
65
|
-
- Add
|
66
|
-
-
|
67
|
-
-
|
116
|
+
- Add saltstack support to configure the application
|
117
|
+
- "git" support for the ansible playbooks
|
118
|
+
- Automatically run the ansible playbook after all hosts are deployed
|
119
|
+
- More parameter / value validation
|
120
|
+
- Deliver ansible playbooks to the connected foreman smart proxies
|
121
|
+
|
68
122
|
|
69
123
|
## Contributing
|
70
124
|
|
@@ -72,7 +126,7 @@ Fork and send a Pull Request. Thanks!
|
|
72
126
|
|
73
127
|
## Copyright
|
74
128
|
|
75
|
-
Copyright (c)
|
129
|
+
Copyright (c) 2020 ATIX AG
|
76
130
|
|
77
131
|
This program is free software: you can redistribute it and/or modify
|
78
132
|
it under the terms of the GNU General Public License as published by
|
@@ -86,4 +140,3 @@ GNU General Public License for more details.
|
|
86
140
|
|
87
141
|
You should have received a copy of the GNU General Public License
|
88
142
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
89
|
-
|
@@ -86,11 +86,11 @@ module ForemanAcd
|
|
86
86
|
|
87
87
|
# We need to support: group_vars/group_file and group_vars/group_dir/yaml_files
|
88
88
|
dir_and_file = File.split(vars_file)
|
89
|
-
|
90
|
-
if basename == 'group_vars'
|
91
|
-
group_name = dir_and_file[1]
|
92
|
-
else
|
93
|
-
group_name = basename
|
89
|
+
|
90
|
+
if File.basename(dir_and_file[0]) == 'group_vars' # in case of group_vars/group_file
|
91
|
+
group_name = File.basename(dir_and_file[1], '.*')
|
92
|
+
else # in case of group_vars/group_dir/yaml_files
|
93
|
+
group_name = File.basename(dir_and_file[0])
|
94
94
|
end
|
95
95
|
|
96
96
|
logger.debug("Add ansible vars from file #{vars_file} to group #{group_name}")
|
@@ -16,7 +16,8 @@ module ForemanAcd
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def read_ansible_playbooks
|
19
|
-
|
19
|
+
# Only use ansible playbooks for which the user pressed import group vars once.
|
20
|
+
@ansible_playbooks = AnsiblePlaybook.where.not(vars: nil).map { |elem| { elem.id => elem.name } }.reduce({}) { |h, v| h.merge v }
|
20
21
|
end
|
21
22
|
|
22
23
|
def read_hostgroups
|
@@ -6,17 +6,13 @@ module ForemanAcd
|
|
6
6
|
include Foreman::Controller::AutoCompleteSearch
|
7
7
|
include ::ForemanAcd::Concerns::AppInstanceParameters
|
8
8
|
|
9
|
-
before_action :find_resource, :only => [:edit, :update, :destroy, :deploy, :report
|
9
|
+
before_action :find_resource, :only => [:edit, :update, :destroy, :deploy, :report]
|
10
10
|
before_action :read_applications, :only => [:new, :edit]
|
11
11
|
|
12
12
|
def index
|
13
13
|
@app_instances = resource_base.search_for(params[:search], :order => params[:order]).paginate(:page => params[:page])
|
14
14
|
end
|
15
15
|
|
16
|
-
def read_applications
|
17
|
-
@applications = AppDefinition.all.map { |elem| { elem.id => elem.name } }.reduce({}) { |h, v| h.merge v }
|
18
|
-
end
|
19
|
-
|
20
16
|
def new
|
21
17
|
@app_instance = AppInstance.new
|
22
18
|
end
|
@@ -55,8 +51,6 @@ module ForemanAcd
|
|
55
51
|
:deploy
|
56
52
|
when 'report'
|
57
53
|
:report
|
58
|
-
when 'configure'
|
59
|
-
:configure
|
60
54
|
else
|
61
55
|
super
|
62
56
|
end
|
@@ -64,51 +58,35 @@ module ForemanAcd
|
|
64
58
|
|
65
59
|
def deploy
|
66
60
|
app_deployer = ForemanAcd::AppDeployer.new(@app_instance)
|
61
|
+
app_hosts = app_deployer.deploy
|
67
62
|
|
68
63
|
# save any change to the app_hosts json
|
69
|
-
@app_instance.hosts =
|
64
|
+
@app_instance.hosts = app_hosts.to_json
|
70
65
|
@app_instance.save
|
71
66
|
|
72
|
-
@deploy_hosts =
|
67
|
+
@deploy_hosts = collect_host_report_data(app_hosts)
|
73
68
|
end
|
74
69
|
|
75
70
|
def report
|
76
|
-
@report_hosts = []
|
77
71
|
app_hosts = JSON.parse(@app_instance.hosts)
|
78
|
-
|
79
|
-
h = Host.find(host_data['foreman_host_id'])
|
80
|
-
@report_hosts.push({id: h.id, name: host_data['hostname'], hostname: h.hostname, hostUrl: host_path(h), powerStatusUrl: power_api_host_path(h) })
|
81
|
-
end
|
72
|
+
@report_hosts = collect_host_report_data(app_hosts)
|
82
73
|
|
83
74
|
logger.debug("deploy report hosts are: #{@report_hosts.inspect}")
|
84
75
|
end
|
85
76
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
logger.debug("Created #{job_count} to configure #{@app_instance} - customize: #{customize_first}")
|
98
|
-
|
99
|
-
if job_count == 1 && customize_first == false
|
100
|
-
jobs.first.trigger!
|
101
|
-
redirect_to job_invocation_path(jobs.first.job_invocation)
|
102
|
-
elsif customize_first == false
|
103
|
-
jobs.each do |composer|
|
104
|
-
composer.save
|
105
|
-
end
|
106
|
-
# redirect to the job itself if we want to customize the job
|
107
|
-
redirect_to job_invocations_path
|
108
|
-
else
|
109
|
-
# redirect to the job itself if we only have one job, otherwise to the index page
|
110
|
-
redirect_to job_invocations_path
|
77
|
+
private
|
78
|
+
|
79
|
+
def read_applications
|
80
|
+
@applications = AppDefinition.all.map { |elem| { elem.id => elem.name } }.reduce({}) { |h, v| h.merge v }
|
81
|
+
end
|
82
|
+
|
83
|
+
def collect_host_report_data(app_hosts)
|
84
|
+
report_data = []
|
85
|
+
app_hosts.each do |host_data|
|
86
|
+
host = Host.find(host_data['foreman_host_id'])
|
87
|
+
report_data << { id: host.id, name: host_data['hostname'], hostname: host.hostname, hostUrl: host_path(host), progress_report_id: host.progress_report_id}
|
111
88
|
end
|
89
|
+
report_data
|
112
90
|
end
|
113
91
|
end
|
114
92
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanAcd
|
4
|
+
# Class to run remote execution jobs
|
5
|
+
class RemoteExecutionController < JobInvocationsController
|
6
|
+
|
7
|
+
def new
|
8
|
+
jobs = init_configuration
|
9
|
+
@composer = jobs.first
|
10
|
+
end
|
11
|
+
|
12
|
+
def create
|
13
|
+
customize_first = params[:customize] || false
|
14
|
+
jobs = init_configuration
|
15
|
+
|
16
|
+
if jobs.count == 1 && customize_first == false
|
17
|
+
@composer = jobs.first
|
18
|
+
@composer.trigger!
|
19
|
+
redirect_to job_invocation_path(@composer.job_invocation)
|
20
|
+
elsif customize_first == false
|
21
|
+
jobs.each do |composer|
|
22
|
+
composer.trigger
|
23
|
+
end
|
24
|
+
# redirect to the job itself if we want to customize the job
|
25
|
+
redirect_to job_invocations_path
|
26
|
+
else
|
27
|
+
@composer = jobs.first
|
28
|
+
render :action => 'new'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# to overcome the isolated namespace engine difficulties with paths
|
33
|
+
helper Rails.application.routes.url_helpers
|
34
|
+
def _routes
|
35
|
+
Rails.application.routes
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def init_configuration
|
41
|
+
app_instance = ForemanAcd::AppInstance.find_by(:name => params[:id])
|
42
|
+
app_configurator = ForemanAcd::AppConfigurator.new(app_instance)
|
43
|
+
|
44
|
+
jobs = app_configurator.configure
|
45
|
+
logger.debug("Creating #{jobs.count} job(s) to configure the app #{app_instance}. Customize first: #{params[:customize]}")
|
46
|
+
return jobs
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -8,7 +8,7 @@ module ForemanAcd
|
|
8
8
|
friendly_id :name
|
9
9
|
|
10
10
|
self.table_name = 'acd_ansible_playbooks'
|
11
|
-
has_many :app_definitions, :inverse_of => :ansible_playbook, :
|
11
|
+
has_many :app_definitions, :inverse_of => :ansible_playbook, :foreign_key => 'acd_ansible_playbook_id', dependent: :restrict_with_error
|
12
12
|
validates :name, :presence => true, :uniqueness => true
|
13
13
|
scoped_search :on => :name
|
14
14
|
default_scope -> { order("acd_ansible_playbooks.name") }
|
@@ -5,11 +5,9 @@ module ForemanAcd
|
|
5
5
|
class AppDeployer
|
6
6
|
|
7
7
|
delegate :logger, :to => :Rails
|
8
|
-
attr_reader :deploy_hosts
|
9
8
|
|
10
9
|
def initialize(app_instance)
|
11
10
|
@app_instance = app_instance
|
12
|
-
@deploy_hosts = []
|
13
11
|
end
|
14
12
|
|
15
13
|
def deploy
|
@@ -44,7 +42,7 @@ module ForemanAcd
|
|
44
42
|
end
|
45
43
|
|
46
44
|
# REMOVE ME (but very nice for testing)
|
47
|
-
#host.mac = "00:11:22:33:44:55"
|
45
|
+
# host.mac = "00:11:22:33:44:55"
|
48
46
|
|
49
47
|
apply_compute_profile(host)
|
50
48
|
host.suggest_default_pxe_loader
|
@@ -52,8 +50,6 @@ module ForemanAcd
|
|
52
50
|
|
53
51
|
# save the foreman host id
|
54
52
|
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
53
|
rescue StandardError => e
|
58
54
|
logger.error("Failed to initiate host creation: #{e.class}: #{e.message}\n#{e.backtrace.join($INPUT_RECORD_SEPARATOR)}")
|
59
55
|
end
|
@@ -16,9 +16,9 @@
|
|
16
16
|
<td><%= ansible_playbook.description %></td>
|
17
17
|
<td>
|
18
18
|
<%= action_buttons(
|
19
|
+
display_link_if_authorized(_("Import group variables"), hash_for_import_vars_ansible_playbook_path(:id => ansible_playbook).merge(:auth_object => ansible_playbook, :authorizer => authorizer)),
|
19
20
|
display_delete_if_authorized(hash_for_ansible_playbook_path(:id => ansible_playbook).merge(:auth_object => ansible_playbook, :authorizer => authorizer),
|
20
|
-
:data => { 'confirm': _('Delete %s?') % ansible_playbook.name })
|
21
|
-
display_link_if_authorized(_("Import group variables"), hash_for_import_vars_ansible_playbook_path(:id => ansible_playbook).merge(:auth_object => ansible_playbook, :authorizer => authorizer))
|
21
|
+
:data => { 'confirm': _('Delete %s?') % ansible_playbook.name })
|
22
22
|
) %>
|
23
23
|
</td>
|
24
24
|
</tr>
|
@@ -17,9 +17,9 @@
|
|
17
17
|
<td>
|
18
18
|
<%= action_buttons(display_link_if_authorized(_("Deploy"), hash_for_deploy_app_instance_path(:id => app_instance), :method => :post,
|
19
19
|
:title => _("Deploy application #{app_instance}")),
|
20
|
-
display_link_if_authorized(_("Run Playbook"),
|
20
|
+
display_link_if_authorized(_("Run Playbook"), hash_for_remote_execution_path(:id => app_instance), :method => :post,
|
21
21
|
:title => _("Run ansible playbook for application #{app_instance}")),
|
22
|
-
display_link_if_authorized(_("Run Playbook - customize first"),
|
22
|
+
display_link_if_authorized(_("Run Playbook - customize first"), hash_for_remote_execution_path(:id => app_instance, :customize => true), :method => :post,
|
23
23
|
:title => _("Prepare job to run ansible playbook for application #{app_instance}")),
|
24
24
|
display_link_if_authorized(_("Report"), hash_for_report_app_instance_path(:id => app_instance), :method => :get,
|
25
25
|
:title => _("Show last deployment report for application #{app_instance}")),
|
data/config/routes.rb
CHANGED
@@ -31,11 +31,12 @@ Rails.application.routes.draw do
|
|
31
31
|
|
32
32
|
member do
|
33
33
|
post 'deploy'
|
34
|
-
post 'configure'
|
35
34
|
get 'report'
|
36
35
|
end
|
37
36
|
end
|
38
37
|
|
38
|
+
match '/remote_execution', :controller => 'foreman_acd/remote_execution', :action => 'create', :via => [:post]
|
39
|
+
|
39
40
|
get 'ui_acd_app/:id', :to => 'ui_acd#app', :constraints => { :id => /[\w\.-]+/ }, :as => :ui_acd_app
|
40
41
|
get 'ui_acd_foreman_data/:id', :to => 'ui_acd#foreman_data', :constraints => { :id => /[\w\.-]+/ }, :as => :ui_acd_foreman_data
|
41
42
|
get 'ui_acd_ansible_data/:id', :to => 'ui_acd#ansible_data', :constraints => { :id => /[\w\.-]+/ }, :as => :ui_acd_ansible_data
|
data/lib/foreman_acd/version.rb
CHANGED
@@ -11,7 +11,8 @@ import Select from 'foremanReact/components/common/forms/Select';
|
|
11
11
|
import ParameterSelection from '../ParameterSelection';
|
12
12
|
import AddTableEntry from '../common/AddTableEntry';
|
13
13
|
import DeleteTableEntry from '../common/DeleteTableEntry';
|
14
|
-
import RailsData from '../common/RailsData'
|
14
|
+
import RailsData from '../common/RailsData';
|
15
|
+
import EasyHeaderFormatter from '../common/EasyHeaderFormatter';
|
15
16
|
import AnsiblePlaybookSelector from './components/AnsiblePlaybookSelector';
|
16
17
|
|
17
18
|
import {
|
@@ -118,8 +119,7 @@ class ApplicationDefinition extends React.Component {
|
|
118
119
|
});
|
119
120
|
this.inlineEditButtonsFormatter = inlineEditButtonsFormatter;
|
120
121
|
|
121
|
-
|
122
|
-
this.headerFormatter = headerFormatter;
|
122
|
+
this.headerFormatter = EasyHeaderFormatter;
|
123
123
|
|
124
124
|
const inlineEditFormatterImpl = {
|
125
125
|
renderValue: (value, additionalData) => (
|
@@ -55,7 +55,7 @@ export const initApplicationDefinition = (
|
|
55
55
|
props: {
|
56
56
|
index: 0,
|
57
57
|
style: {
|
58
|
-
width: '
|
58
|
+
width: '15%'
|
59
59
|
}
|
60
60
|
},
|
61
61
|
},
|
@@ -71,7 +71,7 @@ export const initApplicationDefinition = (
|
|
71
71
|
props: {
|
72
72
|
index: 1,
|
73
73
|
style: {
|
74
|
-
width: '
|
74
|
+
width: '10%'
|
75
75
|
}
|
76
76
|
},
|
77
77
|
},
|
@@ -151,7 +151,7 @@ export const initApplicationDefinition = (
|
|
151
151
|
props: {
|
152
152
|
index: 6,
|
153
153
|
style: {
|
154
|
-
width: '
|
154
|
+
width: '15%'
|
155
155
|
}
|
156
156
|
},
|
157
157
|
},
|
@@ -10,7 +10,8 @@ import Select from 'foremanReact/components/common/forms/Select';
|
|
10
10
|
import ParameterSelection from '../ParameterSelection';
|
11
11
|
import AddTableEntry from '../common/AddTableEntry';
|
12
12
|
import DeleteTableEntry from '../common/DeleteTableEntry';
|
13
|
-
import RailsData from '../common/RailsData'
|
13
|
+
import RailsData from '../common/RailsData';
|
14
|
+
import EasyHeaderFormatter from '../common/EasyHeaderFormatter';
|
14
15
|
import AppDefinitionSelector from './components/AppDefinitionSelector';
|
15
16
|
import ServiceCounter from './components/ServiceCounter';
|
16
17
|
import { arrayToObject } from '../../helper';
|
@@ -145,8 +146,7 @@ class ApplicationInstance extends React.Component {
|
|
145
146
|
});
|
146
147
|
this.inlineEditButtonsFormatter = inlineEditButtonsFormatter;
|
147
148
|
|
148
|
-
|
149
|
-
this.headerFormatter = headerFormatter;
|
149
|
+
this.headerFormatter = EasyHeaderFormatter;
|
150
150
|
|
151
151
|
const inlineEditFormatterImpl = {
|
152
152
|
renderValue: (value, additionalData) => (
|
@@ -50,7 +50,7 @@ export const initApplicationInstance = (
|
|
50
50
|
props: {
|
51
51
|
index: 0,
|
52
52
|
style: {
|
53
|
-
width: '
|
53
|
+
width: '30%'
|
54
54
|
}
|
55
55
|
},
|
56
56
|
},
|
@@ -66,7 +66,7 @@ export const initApplicationInstance = (
|
|
66
66
|
props: {
|
67
67
|
index: 1,
|
68
68
|
style: {
|
69
|
-
width: '
|
69
|
+
width: '30%'
|
70
70
|
}
|
71
71
|
},
|
72
72
|
},
|
@@ -77,7 +77,7 @@ export const initParameterSelection = (
|
|
77
77
|
props: {
|
78
78
|
sort: true,
|
79
79
|
style: {
|
80
|
-
width: '
|
80
|
+
width: '25%'
|
81
81
|
}
|
82
82
|
},
|
83
83
|
transforms: [sortableTransform],
|
@@ -96,7 +96,7 @@ export const initParameterSelection = (
|
|
96
96
|
props: {
|
97
97
|
sort: true,
|
98
98
|
style: {
|
99
|
-
width: '
|
99
|
+
width: '25%'
|
100
100
|
}
|
101
101
|
},
|
102
102
|
transforms: [sortableTransform],
|
@@ -159,7 +159,7 @@ export const initParameterSelection = (
|
|
159
159
|
label: 'Actions',
|
160
160
|
props: {
|
161
161
|
style: {
|
162
|
-
width: '
|
162
|
+
width: '10%'
|
163
163
|
}
|
164
164
|
},
|
165
165
|
formatters: [actionHeaderCellFormatter]
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import {
|
4
|
+
Table,
|
5
|
+
} from 'patternfly-react';
|
6
|
+
|
7
|
+
const EasyHeaderFormatter = (value, { column }) => (
|
8
|
+
<Table.Heading aria-label={column.header.label} {...column.header.props}>
|
9
|
+
{value}
|
10
|
+
</Table.Heading>
|
11
|
+
);
|
12
|
+
|
13
|
+
EasyHeaderFormatter.propTypes = {
|
14
|
+
value: PropTypes.string.isRequired,
|
15
|
+
column: PropTypes.object.isRequired,
|
16
|
+
};
|
17
|
+
|
18
|
+
export default EasyHeaderFormatter;
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman_acd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ATIX AG
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-12-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubocop
|
@@ -62,6 +62,7 @@ files:
|
|
62
62
|
- app/controllers/foreman_acd/concerns/ansible_playbook_parameters.rb
|
63
63
|
- app/controllers/foreman_acd/concerns/app_definition_parameters.rb
|
64
64
|
- app/controllers/foreman_acd/concerns/app_instance_parameters.rb
|
65
|
+
- app/controllers/foreman_acd/remote_execution_controller.rb
|
65
66
|
- app/controllers/ui_acd_controller.rb
|
66
67
|
- app/models/foreman_acd/ansible_playbook.rb
|
67
68
|
- app/models/foreman_acd/app_definition.rb
|
@@ -175,6 +176,7 @@ files:
|
|
175
176
|
- webpack/components/ParameterSelection/index.js
|
176
177
|
- webpack/components/common/AddTableEntry.js
|
177
178
|
- webpack/components/common/DeleteTableEntry.js
|
179
|
+
- webpack/components/common/EasyHeaderFormatter.js
|
178
180
|
- webpack/components/common/ExtSelect.js
|
179
181
|
- webpack/components/common/RailsData.js
|
180
182
|
- webpack/components/common/__tests__/AddTableEntry.test.js
|