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 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