foreman_acd 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +19 -17
- data/app/controllers/foreman_acd/api/v2/ansible_playbooks_controller.rb +20 -3
- data/app/controllers/foreman_acd/remote_execution_controller.rb +1 -1
- data/app/models/foreman_acd/acd_provider.rb +27 -0
- data/app/services/foreman_acd/app_configurator.rb +7 -20
- data/app/views/templates/job/run_acd_ansible_playbook.erb +13 -13
- data/config/routes.rb +5 -1
- data/db/seeds.d/62_acd_proxy_feature.rb +6 -0
- data/lib/foreman_acd/engine.rb +4 -0
- data/lib/foreman_acd/plugin.rb +18 -15
- data/lib/foreman_acd/version.rb +1 -1
- data/webpack/components/ApplicationDefinition/ApplicationDefinition.js +2 -0
- data/webpack/components/ApplicationInstance/ApplicationInstance.js +2 -0
- data/webpack/components/ParameterSelection/ParameterSelection.js +30 -14
- data/webpack/components/ParameterSelection/ParameterSelectionActions.js +8 -0
- data/webpack/components/ParameterSelection/ParameterSelectionConstants.js +1 -0
- data/webpack/components/ParameterSelection/ParameterSelectionReducer.js +16 -1
- data/webpack/components/common/DeleteTableEntry.js +0 -1
- data/webpack/components/common/EditTableEntry.js +49 -0
- data/webpack/components/common/LockTableEntry.js +59 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d211aae9186f8f78068084f48a57c33bcc12840c8c187345a195ce90b474b62
|
4
|
+
data.tar.gz: ffdefcc21d390b4cd379cae7f5884a1660303408824206bcede99dfc00cac23b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 596cce7e2dc9f22f8e53da0060d327e3649963a03df3b89bc60e454698c8318f96d2500dc266ef3a430da959437601154ee00682a416baeaaa0db119f2027d36
|
7
|
+
data.tar.gz: 357f087227ff418cf2ed0cbcf18e0ec5487fdb55c985c35fe55dea387f93db7eb1ec4268a312e325f925621bdb2cf16fdad1d06b13e893bce672e8d1aa03d2c3
|
data/README.md
CHANGED
@@ -40,11 +40,18 @@ This plugin aims to setup all 6 hosts and to deploy the application.
|
|
40
40
|
- Deploy these hosts
|
41
41
|
- Configure the hosts using the configured ansible playbook
|
42
42
|
|
43
|
+
# How it works
|
44
|
+
|
45
|
+
- Configure ansible playbook, application definition and create an instance.
|
46
|
+
- If you deploy the application instance, all hosts are created.
|
47
|
+
- When done, you can configure the hosts with the linked ansible-playbook.
|
48
|
+
- To do so, the [Smart Proxy ACD](https://github.com/ATIX-AG/smart_proxy_acd) is used.
|
49
|
+
- The job to configure the hosts will be send to the Smart Proxy ACD which will
|
50
|
+
- download the ansible playbook from foreman (provided by an foreman_acd API)
|
51
|
+
- extract the ansible playbook on the Smart Proxy
|
52
|
+
- run the ansible-playbook on the Smart Proxy
|
53
|
+
- On the Monitor -> Job page you see the output of the ansible-playbook run.
|
43
54
|
|
44
|
-
# Road Map
|
45
|
-
-
|
46
|
-
- Add Application deployment with single host requirements
|
47
|
-
- Add Application deployment with multi host requirements
|
48
55
|
|
49
56
|
## WARNING
|
50
57
|
|
@@ -55,10 +62,12 @@ This plugin is in development.
|
|
55
62
|
See [How_to_Install_a_Plugin](https://theforeman.org/plugins/#2.Installation)
|
56
63
|
for how to install Foreman plugins.
|
57
64
|
|
65
|
+
You will need to install [Smart Proxy ACD](https://github.com/ATIX-AG/smart_proxy_acd), too.
|
66
|
+
|
58
67
|
### TL;DR:
|
59
68
|
|
60
|
-
yum install tfm-rubygem-foreman_acd
|
61
|
-
foreman-maintain service restart
|
69
|
+
yum install tfm-rubygem-foreman_acd tfm-rubygem-smart_proxy_acd tfm-rubygem-smart_proxy_acd_core
|
70
|
+
foreman-maintain service restart
|
62
71
|
|
63
72
|
In some cases you need to do manally
|
64
73
|
|
@@ -69,14 +78,6 @@ In some cases you need to do manally
|
|
69
78
|
|
70
79
|
Katello plugin need to exist, too.
|
71
80
|
|
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.
|
79
|
-
|
80
81
|
## Usage
|
81
82
|
|
82
83
|
### Ansible Playbook
|
@@ -113,11 +114,12 @@ Make sure, that the job template 'Run ACD Ansible Playbook - SSH Default' is par
|
|
113
114
|
|
114
115
|
## TODO
|
115
116
|
|
116
|
-
- Add saltstack support to configure the application
|
117
117
|
- "git" support for the ansible playbooks
|
118
|
+
- Provide application templates which contains application definition and
|
119
|
+
the required ansible-playbook.
|
120
|
+
- Add saltstack support to configure the application
|
118
121
|
- Automatically run the ansible playbook after all hosts are deployed
|
119
122
|
- More parameter / value validation
|
120
|
-
- Deliver ansible playbooks to the connected foreman smart proxies
|
121
123
|
|
122
124
|
|
123
125
|
## Contributing
|
@@ -126,7 +128,7 @@ Fork and send a Pull Request. Thanks!
|
|
126
128
|
|
127
129
|
## Copyright
|
128
130
|
|
129
|
-
Copyright (c)
|
131
|
+
Copyright (c) 2021 ATIX AG
|
130
132
|
|
131
133
|
This program is free software: you can redistribute it and/or modify
|
132
134
|
it under the terms of the GNU General Public License as published by
|
@@ -5,9 +5,12 @@ module ForemanAcd
|
|
5
5
|
module V2
|
6
6
|
# API controller for Ansible Playbooks
|
7
7
|
class AnsiblePlaybooksController < ::ForemanAcd::Api::V2::BaseController
|
8
|
+
include ::Foreman::Controller::SmartProxyAuth
|
8
9
|
include ::ForemanAcd::Concerns::AnsiblePlaybookParameters
|
9
10
|
|
10
|
-
before_action :find_resource, :except => [:index, :create]
|
11
|
+
before_action :find_resource, :except => [:index, :create, :grab]
|
12
|
+
|
13
|
+
add_smart_proxy_filters :grab, :features => 'ACD'
|
11
14
|
|
12
15
|
api :GET, '/ansible_playbooks/:id', N_('Show ansible playbook')
|
13
16
|
param :id, :identifier, :required => true
|
@@ -41,8 +44,22 @@ module ForemanAcd
|
|
41
44
|
process_response @ansible_playbook.destroy
|
42
45
|
end
|
43
46
|
|
44
|
-
|
45
|
-
|
47
|
+
api :GET, '/ansible_playbooks/:id/grab', N_('Grab ansible playbook')
|
48
|
+
param :id, :identifier, :required => true
|
49
|
+
def grab
|
50
|
+
ap = resource_class.find(params['id'])
|
51
|
+
command = "tar cz -C #{ap.path} --exclude \".git\" . 2>/dev/null | base64"
|
52
|
+
result = %x<#{command}>
|
53
|
+
send_data result, type: "text/plain", disposition: 'inline'
|
54
|
+
end
|
55
|
+
|
56
|
+
def action_permission
|
57
|
+
case params[:action]
|
58
|
+
when 'grab'
|
59
|
+
'grab'
|
60
|
+
else
|
61
|
+
super
|
62
|
+
end
|
46
63
|
end
|
47
64
|
|
48
65
|
def resource_class
|
@@ -21,9 +21,9 @@ module ForemanAcd
|
|
21
21
|
jobs.each do |composer|
|
22
22
|
composer.trigger
|
23
23
|
end
|
24
|
-
# redirect to the job itself if we want to customize the job
|
25
24
|
redirect_to job_invocations_path
|
26
25
|
else
|
26
|
+
# redirect to the job itself if we want to customize the job
|
27
27
|
@composer = jobs.first
|
28
28
|
render :action => 'new'
|
29
29
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ForemanAcd
|
2
|
+
class AcdProvider < RemoteExecutionProvider
|
3
|
+
class << self
|
4
|
+
def supports_effective_user?
|
5
|
+
true
|
6
|
+
end
|
7
|
+
|
8
|
+
def proxy_operation_name
|
9
|
+
'acd'
|
10
|
+
end
|
11
|
+
|
12
|
+
def humanized_name
|
13
|
+
'ACD'
|
14
|
+
end
|
15
|
+
|
16
|
+
def proxy_command_options(template_invocation, host)
|
17
|
+
super(template_invocation, host).merge(:name => host.name)
|
18
|
+
end
|
19
|
+
|
20
|
+
def ssh_password(_host); end
|
21
|
+
|
22
|
+
def ssh_key_passphrase(_host); end
|
23
|
+
|
24
|
+
def sudo_password(_host); end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -13,14 +13,8 @@ module ForemanAcd
|
|
13
13
|
def configure
|
14
14
|
job_input = {}
|
15
15
|
job_input['application_name'] = @app_instance.name
|
16
|
-
job_input['
|
17
|
-
job_input['
|
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
|
16
|
+
job_input['playbook_id'] = @app_instance.app_definition.ansible_playbook.id
|
17
|
+
job_input['playbook_file'] = @app_instance.app_definition.ansible_playbook.playfile
|
24
18
|
|
25
19
|
logger.info("Use inventory to configure #{@app_instance.name} with ansible playbook #{@app_instance.app_definition.ansible_playbook.name}")
|
26
20
|
|
@@ -47,18 +41,11 @@ module ForemanAcd
|
|
47
41
|
inventory = ForemanAcd::InventoryCreator.new(@app_instance, host_names).create_inventory
|
48
42
|
job_input['inventory'] = YAML.dump(inventory)
|
49
43
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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)
|
44
|
+
composer = JobInvocationComposer.for_feature(
|
45
|
+
:run_acd_ansible_playbook,
|
46
|
+
[Host.find_by(:name => proxy_name).id],
|
47
|
+
job_input.to_hash
|
48
|
+
)
|
62
49
|
jobs << composer
|
63
50
|
end
|
64
51
|
rescue StandardError => e
|
@@ -1,24 +1,24 @@
|
|
1
1
|
<%#
|
2
2
|
kind: job_template
|
3
|
-
name: Run ACD Ansible Playbook -
|
3
|
+
name: Run ACD Ansible Playbook - ACD Default
|
4
4
|
model: JobTemplate
|
5
5
|
job_category: Application Centric Deployment
|
6
6
|
description_format: "Run Ansible playbook %{playbook_name} for ACD application %{application_name}"
|
7
|
-
provider_type: SSH
|
8
7
|
feature: run_acd_ansible_playbook
|
8
|
+
provider_type: ACD
|
9
9
|
template_inputs:
|
10
10
|
- name: application_name
|
11
11
|
description: The name of the ACD application instance to run
|
12
12
|
input_type: user
|
13
13
|
required: true
|
14
14
|
advanced: false
|
15
|
-
- name:
|
16
|
-
description: The
|
15
|
+
- name: playbook_id
|
16
|
+
description: The id of the Ansible playbook to run
|
17
17
|
input_type: user
|
18
18
|
required: true
|
19
19
|
advanced: false
|
20
|
-
- name:
|
21
|
-
description: The
|
20
|
+
- name: playbook_file
|
21
|
+
description: The playbook file of to the Ansible playbook
|
22
22
|
input_type: user
|
23
23
|
required: true
|
24
24
|
advanced: false
|
@@ -40,10 +40,10 @@ template_inputs:
|
|
40
40
|
advanced: true
|
41
41
|
%>
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
<%= input('
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
43
|
+
application_name: <%= input('application_name') %>
|
44
|
+
playbook_id: <%= input('playbook_id') %>
|
45
|
+
playbook_file: <%= input('playbook_file') %>
|
46
|
+
extra_vars: <%= input('extra_vars') %>
|
47
|
+
verbose: <%= input('verbose') %>
|
48
|
+
inventory: |
|
49
|
+
<%= indent(2) { input('inventory') } %>
|
data/config/routes.rb
CHANGED
@@ -47,7 +47,11 @@ Rails.application.routes.draw do
|
|
47
47
|
constraints(:id => /[\w\.-]+/) do
|
48
48
|
resources :app_definitions, :only => [:show, :index], :controller => 'foreman_acd/api/v2/app_definitions', :as => :acd_api_v2_app_definitions
|
49
49
|
resources :app_instances, :only => [:show, :index], :controller => 'foreman_acd/api/v2/app_instances', :as => :api_v2_foreman_acd_app_instances
|
50
|
-
resources :ansible_playbooks, :only => [:show, :index], :controller => 'foreman_acd/api/v2/ansible_playbooks', :as => :api_v2_foreman_acd_ansible_playbooks
|
50
|
+
resources :ansible_playbooks, :only => [:show, :index], :controller => 'foreman_acd/api/v2/ansible_playbooks', :as => :api_v2_foreman_acd_ansible_playbooks do
|
51
|
+
member do
|
52
|
+
get 'grab'
|
53
|
+
end
|
54
|
+
end
|
51
55
|
end
|
52
56
|
end
|
53
57
|
end
|
data/lib/foreman_acd/engine.rb
CHANGED
data/lib/foreman_acd/plugin.rb
CHANGED
@@ -6,21 +6,19 @@ Foreman::Plugin.register :foreman_acd do
|
|
6
6
|
apipie_documented_controllers ["#{ForemanAcd::Engine.root}/app/controllers/foreman_acd/api/v2/*.rb"]
|
7
7
|
|
8
8
|
# Menus
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
:caption => 'App Instances',
|
23
|
-
:parent => :configure_menu
|
9
|
+
sub_menu :top_menu, :application, :caption => N_('Applications'), :after => :hosts_menu, :icon => 'pficon pficon-integration' do
|
10
|
+
menu :top_menu, :ansible_playbooks,
|
11
|
+
:url_hash => { :controller => :'foreman_acd/ansible_playbooks', :action => :index },
|
12
|
+
:caption => 'Ansible Playbooks'
|
13
|
+
|
14
|
+
menu :top_menu, :app_definitions,
|
15
|
+
:url_hash => { :controller => :'foreman_acd/app_definitions', :action => :index },
|
16
|
+
:caption => 'App Definitions'
|
17
|
+
|
18
|
+
menu :top_menu, :app_instances,
|
19
|
+
:url_hash => { :controller => :'foreman_acd/app_instances', :action => :index },
|
20
|
+
:caption => 'App Instances'
|
21
|
+
end
|
24
22
|
|
25
23
|
# Add permissions
|
26
24
|
security_block :foreman_acd do
|
@@ -49,6 +47,10 @@ Foreman::Plugin.register :foreman_acd do
|
|
49
47
|
:'foreman_acd/api/v2/ansible_playbooks' => [:import_vars] },
|
50
48
|
:resource_type => 'ForemanAcd::AnsiblePlaybook'
|
51
49
|
|
50
|
+
permission :grab_ansible_playbooks,
|
51
|
+
{ :'foreman_acd/api/v2/ansible_playbooks' => [:grab] },
|
52
|
+
:resource_type => 'ForemanAcd::AnsiblePlaybook'
|
53
|
+
|
52
54
|
permission :create_app_definitions,
|
53
55
|
{ :'foreman_acd/app_definitions' => [:new, :create],
|
54
56
|
:'foreman_acd/api/v2/app_definitions' => [:create] },
|
@@ -121,6 +123,7 @@ Foreman::Plugin.register :foreman_acd do
|
|
121
123
|
:edit_ansible_playbooks,
|
122
124
|
:destroy_ansible_playbooks,
|
123
125
|
:import_vars_ansible_playbooks,
|
126
|
+
:grab_ansible_playbooks,
|
124
127
|
:create_app_definitions,
|
125
128
|
:view_app_definitions,
|
126
129
|
:edit_app_definitions,
|
data/lib/foreman_acd/version.rb
CHANGED
@@ -86,6 +86,7 @@ class ApplicationDefinition extends React.Component {
|
|
86
86
|
>
|
87
87
|
<span title="change ansible variables">A</span>
|
88
88
|
</Button>
|
89
|
+
|
89
90
|
<DeleteTableEntry
|
90
91
|
hidden={false}
|
91
92
|
disabled={false}
|
@@ -108,6 +109,7 @@ class ApplicationDefinition extends React.Component {
|
|
108
109
|
bsStyle="default" disabled>
|
109
110
|
<span>A</span>
|
110
111
|
</Button>
|
112
|
+
|
111
113
|
<DeleteTableEntry
|
112
114
|
hidden={false}
|
113
115
|
disabled={true}
|
@@ -114,6 +114,7 @@ class ApplicationInstance extends React.Component {
|
|
114
114
|
>
|
115
115
|
<span title="change ansible variables">A</span>
|
116
116
|
</Button>
|
117
|
+
|
117
118
|
<DeleteTableEntry
|
118
119
|
hidden={false}
|
119
120
|
disabled={false}
|
@@ -135,6 +136,7 @@ class ApplicationInstance extends React.Component {
|
|
135
136
|
<Button bsStyle="default" disabled>
|
136
137
|
<span>A</span>
|
137
138
|
</Button>
|
139
|
+
|
138
140
|
<DeleteTableEntry
|
139
141
|
hidden={false}
|
140
142
|
disabled={true}
|
@@ -6,7 +6,9 @@ import { orderBy } from 'lodash';
|
|
6
6
|
import * as resolve from 'table-resolver';
|
7
7
|
import Select from 'foremanReact/components/common/forms/Select';
|
8
8
|
import AddTableEntry from '../common/AddTableEntry';
|
9
|
+
import EditTableEntry from '../common/EditTableEntry';
|
9
10
|
import DeleteTableEntry from '../common/DeleteTableEntry';
|
11
|
+
import LockTableEntry from '../common/LockTableEntry';
|
10
12
|
import ExtSelect from '../common/ExtSelect';
|
11
13
|
|
12
14
|
import {
|
@@ -64,6 +66,7 @@ class ParameterSelection extends React.Component {
|
|
64
66
|
initParameterSelection,
|
65
67
|
sortParameter,
|
66
68
|
deleteParameter,
|
69
|
+
lockParameter,
|
67
70
|
activateEditParameter,
|
68
71
|
changeEditParameter,
|
69
72
|
loadParamData,
|
@@ -83,12 +86,20 @@ class ParameterSelection extends React.Component {
|
|
83
86
|
isEditing: additionalData => this.props.editMode,
|
84
87
|
renderValue: (value, additionalData) => (
|
85
88
|
<td style={{ padding: '2px' }}>
|
86
|
-
<
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
89
|
+
<EditTableEntry
|
90
|
+
disabled={false}
|
91
|
+
handleLocking={!allowRowAdjustment}
|
92
|
+
onEditTableEntry={() => activateEditParameter(additionalData)}
|
93
|
+
additionalData={additionalData}
|
94
|
+
/>
|
95
|
+
|
96
|
+
<LockTableEntry
|
97
|
+
hidden={!allowRowAdjustment}
|
98
|
+
disabled={!allowRowAdjustment}
|
99
|
+
onLockTableEntry={lockParameter}
|
100
|
+
additionalData={additionalData}
|
101
|
+
/>
|
102
|
+
|
92
103
|
<DeleteTableEntry
|
93
104
|
hidden={!allowRowAdjustment}
|
94
105
|
disabled={false}
|
@@ -99,9 +110,18 @@ class ParameterSelection extends React.Component {
|
|
99
110
|
),
|
100
111
|
renderEdit: (value, additionalData) => (
|
101
112
|
<td style={{ padding: '2px' }}>
|
102
|
-
<
|
103
|
-
|
104
|
-
|
113
|
+
<EditTableEntry
|
114
|
+
disabled={true}
|
115
|
+
onEditTableEntry={() => activateEditParameter(additionalData)}
|
116
|
+
additionalData={additionalData}
|
117
|
+
/>
|
118
|
+
|
119
|
+
<LockTableEntry
|
120
|
+
disabled={true}
|
121
|
+
onLockTableEntry={lockParameter}
|
122
|
+
additionalData={additionalData}
|
123
|
+
/>
|
124
|
+
|
105
125
|
<DeleteTableEntry
|
106
126
|
hidden={!allowRowAdjustment}
|
107
127
|
disabled={true}
|
@@ -288,11 +308,6 @@ class ParameterSelection extends React.Component {
|
|
288
308
|
<div>
|
289
309
|
<div className="clearfix">
|
290
310
|
<div className="form-group">
|
291
|
-
<AddTableEntry
|
292
|
-
hidden={!allowRowAdjustment}
|
293
|
-
disabled={ this.props.editMode }
|
294
|
-
onAddTableEntry={ addParameter }
|
295
|
-
/>
|
296
311
|
<Table.PfProvider
|
297
312
|
striped
|
298
313
|
bordered
|
@@ -370,6 +385,7 @@ ParameterSelection.propTypes = {
|
|
370
385
|
sortParameter: PropTypes.func,
|
371
386
|
addParameter: PropTypes.func,
|
372
387
|
deleteParameter: PropTypes.func,
|
388
|
+
lockParameter: PropTypes.func,
|
373
389
|
activateEditParameter: PropTypes.func,
|
374
390
|
confirmEditParameter: PropTypes.func,
|
375
391
|
cancelEditParameter: PropTypes.func,
|
@@ -22,6 +22,7 @@ import {
|
|
22
22
|
import {
|
23
23
|
PARAMETER_SELECTION_INIT,
|
24
24
|
PARAMETER_SELECTION_TYPES,
|
25
|
+
PARAMETER_SELECTION_LOCK,
|
25
26
|
PARAMETER_SELECTION_DELETE,
|
26
27
|
PARAMETER_SELECTION_ADD,
|
27
28
|
PARAMETER_SELECTION_EDIT_ACTIVATE,
|
@@ -189,6 +190,13 @@ const errorHandler = (msg, err) => {
|
|
189
190
|
return { type: msg, payload: { error } };
|
190
191
|
};
|
191
192
|
|
193
|
+
export const lockParameter = (additionalData) => ({
|
194
|
+
type: PARAMETER_SELECTION_LOCK,
|
195
|
+
payload: {
|
196
|
+
...additionalData,
|
197
|
+
},
|
198
|
+
});
|
199
|
+
|
192
200
|
export const addParameter = (additionalData) => ({
|
193
201
|
type: PARAMETER_SELECTION_ADD,
|
194
202
|
payload: {
|
@@ -1,4 +1,5 @@
|
|
1
1
|
export const PARAMETER_SELECTION_INIT = 'INIT_PARAMETER_SELECTION_INIT';
|
2
|
+
export const PARAMETER_SELECTION_LOCK = 'PARAMETER_SELECTION_LOCK';
|
2
3
|
export const PARAMETER_SELECTION_DELETE = 'PARAMETER_SELECTION_DELETE';
|
3
4
|
export const PARAMETER_SELECTION_ADD = 'PARAMETER_SELECTION_ADD';
|
4
5
|
export const PARAMETER_SELECTION_EDIT_ACTIVATE = 'PARAMETER_SELECTION_EDIT_ACTIVATE';
|
@@ -15,6 +15,7 @@ import * as sort from 'sortabular';
|
|
15
15
|
import {
|
16
16
|
PARAMETER_SELECTION_INIT,
|
17
17
|
PARAMETER_SELECTION_TYPES,
|
18
|
+
PARAMETER_SELECTION_LOCK,
|
18
19
|
PARAMETER_SELECTION_DELETE,
|
19
20
|
PARAMETER_SELECTION_ADD,
|
20
21
|
PARAMETER_SELECTION_EDIT_ACTIVATE,
|
@@ -54,7 +55,7 @@ const parameterSelectionParameters = (state = initialState, action) => {
|
|
54
55
|
index = Math.max(...parameters.map(e => e.id)) + 1;
|
55
56
|
}
|
56
57
|
|
57
|
-
const newRow = {id: index, name: "", description: '', type: '', value: '', newEntry: true };
|
58
|
+
const newRow = {id: index, locked: false, name: "", description: '', type: '', value: '', newEntry: true };
|
58
59
|
newRow.backup = cloneDeep(newRow)
|
59
60
|
parameters.push(newRow);
|
60
61
|
|
@@ -63,6 +64,20 @@ const parameterSelectionParameters = (state = initialState, action) => {
|
|
63
64
|
parameters: parameters
|
64
65
|
});
|
65
66
|
}
|
67
|
+
case PARAMETER_SELECTION_LOCK: {
|
68
|
+
const parameters = cloneDeep(state.parameters);
|
69
|
+
const index = findIndex(parameters, { id: payload.rowData.id });
|
70
|
+
|
71
|
+
if (parameters[index].locked !== undefined) {
|
72
|
+
parameters[index].locked = !parameters[index].locked;
|
73
|
+
} else {
|
74
|
+
parameters[index].locked = true;
|
75
|
+
}
|
76
|
+
|
77
|
+
return state.merge({
|
78
|
+
parameters: parameters
|
79
|
+
});
|
80
|
+
}
|
66
81
|
case PARAMETER_SELECTION_DELETE: {
|
67
82
|
const parameters = state.parameters.filter(v => v.id !== payload.rowData.id);
|
68
83
|
return state.merge({
|
@@ -0,0 +1,49 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import {
|
4
|
+
Icon,
|
5
|
+
Button,
|
6
|
+
} from 'patternfly-react';
|
7
|
+
|
8
|
+
const EditTableEntry = ({
|
9
|
+
hidden,
|
10
|
+
disabled,
|
11
|
+
handleLocking,
|
12
|
+
onEditTableEntry,
|
13
|
+
additionalData,
|
14
|
+
}) =>{
|
15
|
+
if (hidden) {
|
16
|
+
return null;
|
17
|
+
}
|
18
|
+
|
19
|
+
let title = 'edit this entry'
|
20
|
+
|
21
|
+
if (handleLocking === true) {
|
22
|
+
if (additionalData.rowData.locked === true) {
|
23
|
+
disabled = true;
|
24
|
+
title = 'This entry is locked and can not be changed.';
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
return (
|
29
|
+
<span>
|
30
|
+
<Button
|
31
|
+
bsStyle="default"
|
32
|
+
disabled={disabled}
|
33
|
+
onClick={() => onEditTableEntry(additionalData) }
|
34
|
+
>
|
35
|
+
<Icon type="pf" name="edit" title={title} />
|
36
|
+
</Button>
|
37
|
+
</span>
|
38
|
+
);
|
39
|
+
};
|
40
|
+
|
41
|
+
EditTableEntry.propTypes = {
|
42
|
+
hidden: PropTypes.bool,
|
43
|
+
disabled: PropTypes.bool.isRequired,
|
44
|
+
handleLocking: PropTypes.bool.isRequired,
|
45
|
+
onEditTableEntry: PropTypes.func.isRequired,
|
46
|
+
additionalData: PropTypes.object.isRequired,
|
47
|
+
};
|
48
|
+
|
49
|
+
export default EditTableEntry;
|
@@ -0,0 +1,59 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import {
|
4
|
+
Icon,
|
5
|
+
Button,
|
6
|
+
} from 'patternfly-react';
|
7
|
+
|
8
|
+
const LockTableEntry = ({
|
9
|
+
hidden,
|
10
|
+
disabled,
|
11
|
+
onLockTableEntry,
|
12
|
+
additionalData,
|
13
|
+
}) =>{
|
14
|
+
if (hidden) {
|
15
|
+
return null;
|
16
|
+
}
|
17
|
+
|
18
|
+
let lockButton;
|
19
|
+
let lockButtonTitle;
|
20
|
+
|
21
|
+
if (additionalData.rowData.locked === true) {
|
22
|
+
lockButton = 'locked';
|
23
|
+
|
24
|
+
if (disabled === true) {
|
25
|
+
lockButtonTitle = 'this entry is locked';
|
26
|
+
} else {
|
27
|
+
lockButtonTitle = 'unlock this entry';
|
28
|
+
}
|
29
|
+
} else {
|
30
|
+
lockButton = 'unlocked';
|
31
|
+
|
32
|
+
if (disabled === true) {
|
33
|
+
lockButtonTitle = 'this entry is unlocked';
|
34
|
+
} else {
|
35
|
+
lockButtonTitle = 'lock this entry';
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
return (
|
40
|
+
<span>
|
41
|
+
<Button
|
42
|
+
bsStyle="default"
|
43
|
+
disabled={disabled}
|
44
|
+
onClick={() => onLockTableEntry(additionalData) }
|
45
|
+
>
|
46
|
+
<Icon type="pf" name={lockButton} title={lockButtonTitle} />
|
47
|
+
</Button>
|
48
|
+
</span>
|
49
|
+
);
|
50
|
+
};
|
51
|
+
|
52
|
+
LockTableEntry.propTypes = {
|
53
|
+
hidden: PropTypes.bool,
|
54
|
+
disabled: PropTypes.bool.isRequired,
|
55
|
+
onLockTableEntry: PropTypes.func.isRequired,
|
56
|
+
additionalData: PropTypes.object.isRequired,
|
57
|
+
};
|
58
|
+
|
59
|
+
export default LockTableEntry;
|
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.5.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:
|
11
|
+
date: 2021-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubocop
|
@@ -64,6 +64,7 @@ files:
|
|
64
64
|
- app/controllers/foreman_acd/concerns/app_instance_parameters.rb
|
65
65
|
- app/controllers/foreman_acd/remote_execution_controller.rb
|
66
66
|
- app/controllers/ui_acd_controller.rb
|
67
|
+
- app/models/foreman_acd/acd_provider.rb
|
67
68
|
- app/models/foreman_acd/ansible_playbook.rb
|
68
69
|
- app/models/foreman_acd/app_definition.rb
|
69
70
|
- app/models/foreman_acd/app_instance.rb
|
@@ -111,6 +112,7 @@ files:
|
|
111
112
|
- db/migrate/20200917120220_add_ansible_playbook_id.rb
|
112
113
|
- db/migrate/20201016002819_add_ansible_vars_all_to_app_definitions.rb
|
113
114
|
- db/migrate/20201016104338_add_ansible_vars_all_to_app_instances.rb
|
115
|
+
- db/seeds.d/62_acd_proxy_feature.rb
|
114
116
|
- db/seeds.d/75-job_templates.rb
|
115
117
|
- lib/foreman_acd.rb
|
116
118
|
- lib/foreman_acd/engine.rb
|
@@ -177,7 +179,9 @@ files:
|
|
177
179
|
- webpack/components/common/AddTableEntry.js
|
178
180
|
- webpack/components/common/DeleteTableEntry.js
|
179
181
|
- webpack/components/common/EasyHeaderFormatter.js
|
182
|
+
- webpack/components/common/EditTableEntry.js
|
180
183
|
- webpack/components/common/ExtSelect.js
|
184
|
+
- webpack/components/common/LockTableEntry.js
|
181
185
|
- webpack/components/common/RailsData.js
|
182
186
|
- webpack/components/common/__tests__/AddTableEntry.test.js
|
183
187
|
- webpack/components/common/__tests__/DeleteTableEntry.test.js
|