foreman_acd 0.4.0 → 0.5.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 +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
|