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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 433f2c68da81192db3c98fc013ed2149490f2471e84d372db8241522a33b6630
4
- data.tar.gz: aa46c833de3feb1cce0802de82dec78f1610331984e6df8df649fdadfffa2b2a
3
+ metadata.gz: 0d211aae9186f8f78068084f48a57c33bcc12840c8c187345a195ce90b474b62
4
+ data.tar.gz: ffdefcc21d390b4cd379cae7f5884a1660303408824206bcede99dfc00cac23b
5
5
  SHA512:
6
- metadata.gz: 0accbf314dd5776a5b012507d97619be98beff2c11e523da4d27f69e9fdb1bf1d284c134dba6549719312a66ede8cb80c8a06e3851f01a14951b1752ef2e29e8
7
- data.tar.gz: d003bc7a5de1c180b2e33ade4e85b2912776db564d59ff9d8eca4f9ccc00c38591fd061649df07bb89e76ad0b0ac5efe1c64dd506132148aaf087b758a18c078
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 --only foreman
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) 2020 ATIX AG
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
- def controller_permission
45
- 'ansible_playbooks'
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['playbook_name'] = @app_instance.app_definition.ansible_playbook.name
17
- job_input['playbook_path'] = File.join(@app_instance.app_definition.ansible_playbook.path,
18
- @app_instance.app_definition.ansible_playbook.playfile)
19
-
20
- # TODO should or do we really need it to a file?
21
- #inventory_file = File.new("/tmp/acd_inventory_file", "w") # we can also use Tempfile.new() but a tempfile will be deleted soon (after transaction finished)
22
- #inventory_file << inventory.to_yaml
23
- #inventory_file.close
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
- # Unfortunately, we can not use "JobInvocationComposer.for_feature" method
51
- # because then its not possible to the set effective_user
52
- job = JobTemplate.find(RemoteExecutionFeature.feature('run_acd_ansible_playbook').job_template_id)
53
- params = {
54
- :job_category => job.job_category,
55
- :job_template_id => job.id,
56
- :targeting_type => 'static_query',
57
- :search_query => "name = #{proxy_name}",
58
- :effective_user => 'foreman-proxy',
59
- :inputs => job_input.to_hash
60
- }
61
- composer = JobInvocationComposer.from_api_params(params)
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 - SSH Default
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: playbook_name
16
- description: The name of the Ansible playbook to run
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: playbook_path
21
- description: The full path to the Ansible playbook
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
- INVENTORY_FILE=$(mktemp --suffix ".yaml")
44
- cat << EOF >$INVENTORY_FILE
45
- <%= input('inventory') %>
46
- EOF
47
-
48
- echo "Run ansible-playbook <%= input('playbook_name') %> to configure ACD app <%= input('application_name') %>"
49
- ansible-playbook -i $INVENTORY_FILE <%= "-v" if input('verbose').present? && input('verbose') == 'true' %> <%= "--extra-vars \"#{input('extra_vars')}\"" unless input('extra_vars').blank? %> <%= input('playbook_path') %>
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') } %>
@@ -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
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ proxy_feature = Feature.where(:name => 'ACD').first_or_create
4
+ if proxy_feature.nil? || proxy_feature.errors.any?
5
+ raise "Unable to create proxy feature: #{format_errors proxy_feature}"
6
+ end
@@ -42,5 +42,9 @@ module ForemanAcd
42
42
  initializer 'foreman_acd.register_plugin', :before => :finisher_hook do
43
43
  require 'foreman_acd/plugin'
44
44
  end
45
+
46
+ config.to_prepare do
47
+ RemoteExecutionProvider.register(:ACD, AcdProvider)
48
+ end
45
49
  end
46
50
  end
@@ -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
- divider :top_menu, :parent => :configure_menu, :caption => 'Applications'
10
- menu :top_menu, :ansible_playbooks,
11
- :url_hash => { :controller => :'foreman_acd/ansible_playbooks', :action => :index },
12
- :caption => 'Ansible Playbooks',
13
- :parent => :configure_menu
14
-
15
- menu :top_menu, :app_definitions,
16
- :url_hash => { :controller => :'foreman_acd/app_definitions', :action => :index },
17
- :caption => 'App Definitions',
18
- :parent => :configure_menu
19
-
20
- menu :top_menu, :app_instances,
21
- :url_hash => { :controller => :'foreman_acd/app_instances', :action => :index },
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,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ForemanAcd
4
- VERSION = '0.4.0'
4
+ VERSION = '0.5.0'
5
5
  end
@@ -86,6 +86,7 @@ class ApplicationDefinition extends React.Component {
86
86
  >
87
87
  <span title="change ansible variables">A</span>
88
88
  </Button>
89
+ &nbsp;
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
+ &nbsp;
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
+ &nbsp;
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
+ &nbsp;
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
- <Button
87
- bsStyle="default"
88
- onClick={() => activateEditParameter(additionalData)}
89
- >
90
- <Icon type="pf" name="edit" />
91
- </Button>
89
+ <EditTableEntry
90
+ disabled={false}
91
+ handleLocking={!allowRowAdjustment}
92
+ onEditTableEntry={() => activateEditParameter(additionalData)}
93
+ additionalData={additionalData}
94
+ />
95
+ &nbsp;
96
+ <LockTableEntry
97
+ hidden={!allowRowAdjustment}
98
+ disabled={!allowRowAdjustment}
99
+ onLockTableEntry={lockParameter}
100
+ additionalData={additionalData}
101
+ />
102
+ &nbsp;
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
- <Button bsStyle="default" disabled>
103
- <Icon type="pf" name="edit" />
104
- </Button>
113
+ <EditTableEntry
114
+ disabled={true}
115
+ onEditTableEntry={() => activateEditParameter(additionalData)}
116
+ additionalData={additionalData}
117
+ />
118
+ &nbsp;
119
+ <LockTableEntry
120
+ disabled={true}
121
+ onLockTableEntry={lockParameter}
122
+ additionalData={additionalData}
123
+ />
124
+ &nbsp;
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({
@@ -17,7 +17,6 @@ const DeleteTableEntry = ({
17
17
 
18
18
  return (
19
19
  <span>
20
- &nbsp;
21
20
  <Button
22
21
  bsStyle="default"
23
22
  disabled={disabled}
@@ -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.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: 2020-12-14 00:00:00.000000000 Z
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