foreman_acd 0.0.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/foreman_acd/ansible_playbooks_controller.rb +122 -0
  3. data/app/controllers/foreman_acd/api/v2/ansible_playbooks_controller.rb +54 -0
  4. data/app/controllers/foreman_acd/api/v2/app_definitions_controller.rb +1 -2
  5. data/app/controllers/foreman_acd/api/v2/app_instances_controller.rb +54 -0
  6. data/app/controllers/foreman_acd/api/v2/app_playbooks_controller.rb +0 -0
  7. data/app/controllers/foreman_acd/app_definitions_controller.rb +35 -4
  8. data/app/controllers/foreman_acd/app_instances_controller.rb +43 -87
  9. data/app/controllers/foreman_acd/concerns/ansible_playbook_parameters.rb +23 -0
  10. data/app/controllers/foreman_acd/concerns/app_definition_parameters.rb +1 -1
  11. data/app/controllers/foreman_acd/concerns/app_instance_parameters.rb +1 -1
  12. data/app/controllers/ui_acd_controller.rb +11 -4
  13. data/app/models/foreman_acd/ansible_playbook.rb +50 -0
  14. data/app/models/foreman_acd/app_definition.rb +2 -1
  15. data/app/models/foreman_acd/app_instance.rb +7 -0
  16. data/app/services/foreman_acd/app_configurator.rb +70 -0
  17. data/app/services/foreman_acd/app_deployer.rb +143 -0
  18. data/app/services/foreman_acd/inventory_creator.rb +67 -0
  19. data/app/views/foreman_acd/ansible_playbooks/_form.html.erb +21 -0
  20. data/app/views/foreman_acd/ansible_playbooks/edit.html.erb +3 -0
  21. data/app/views/foreman_acd/ansible_playbooks/index.html.erb +30 -0
  22. data/app/views/foreman_acd/ansible_playbooks/new.html.erb +3 -0
  23. data/app/views/foreman_acd/api/v2/ansible_playbooks/base.json.rabl +3 -0
  24. data/app/views/foreman_acd/api/v2/ansible_playbooks/index.json.rabl +3 -0
  25. data/app/views/foreman_acd/api/v2/ansible_playbooks/show.json.rabl +3 -0
  26. data/app/views/foreman_acd/api/v2/app_definitions/base.json.rabl +3 -0
  27. data/app/views/foreman_acd/api/v2/app_definitions/index.json.rabl +3 -0
  28. data/app/views/foreman_acd/api/v2/app_definitions/show.json.rabl +3 -0
  29. data/app/views/foreman_acd/api/v2/app_instances/base.json.rabl +3 -0
  30. data/app/views/foreman_acd/api/v2/app_instances/index.json.rabl +3 -0
  31. data/app/views/foreman_acd/api/v2/app_instances/show.json.rabl +3 -0
  32. data/app/views/foreman_acd/app_definitions/_form.html.erb +25 -19
  33. data/app/views/foreman_acd/app_definitions/edit.html.erb +5 -0
  34. data/app/views/foreman_acd/app_definitions/import.html.erb +18 -0
  35. data/app/views/foreman_acd/app_definitions/index.html.erb +9 -5
  36. data/app/views/foreman_acd/app_instances/_form.html.erb +10 -8
  37. data/app/views/foreman_acd/app_instances/deploy.html.erb +19 -0
  38. data/app/views/foreman_acd/app_instances/index.html.erb +10 -5
  39. data/app/views/foreman_acd/app_instances/report.html.erb +19 -0
  40. data/app/views/templates/job/run_acd_ansible_playbook.erb +49 -0
  41. data/app/views/ui_acd/ansible_data.json.rabl +6 -0
  42. data/app/views/ui_acd/app.json.rabl +6 -2
  43. data/app/views/ui_acd/app_definition.json.rabl +1 -1
  44. data/app/views/ui_acd/{fdata.json.rabl → foreman_data.json.rabl} +1 -1
  45. data/config/routes.rb +31 -1
  46. data/db/migrate/20190610202252_create_app_definitions.rb +1 -3
  47. data/db/migrate/20190625140305_create_app_instances.rb +1 -1
  48. data/db/migrate/20200916091018_create_ansible_playbooks.rb +20 -0
  49. data/db/migrate/20200917120220_add_ansible_playbook_id.rb +14 -0
  50. data/db/migrate/20201016002819_add_ansible_vars_all_to_app_definitions.rb +5 -0
  51. data/db/migrate/20201016104338_add_ansible_vars_all_to_app_instances.rb +5 -0
  52. data/db/seeds.d/75-job_templates.rb +8 -0
  53. data/lib/foreman_acd/engine.rb +3 -0
  54. data/lib/foreman_acd/plugin.rb +72 -4
  55. data/lib/foreman_acd/version.rb +1 -1
  56. data/package.json +2 -1
  57. data/webpack/components/ApplicationDefinition/ApplicationDefinition.js +376 -0
  58. data/webpack/components/ApplicationDefinition/ApplicationDefinition.scss +1 -0
  59. data/webpack/components/ApplicationDefinition/ApplicationDefinitionActions.js +295 -0
  60. data/webpack/components/ApplicationDefinition/ApplicationDefinitionConstants.js +14 -0
  61. data/webpack/components/ApplicationDefinition/ApplicationDefinitionHelper.js +26 -0
  62. data/webpack/components/ApplicationDefinition/ApplicationDefinitionReducer.js +243 -0
  63. data/webpack/components/ApplicationDefinition/ApplicationDefinitionSelectors.js +8 -0
  64. data/webpack/components/ApplicationDefinition/components/AnsiblePlaybookSelector.js +49 -0
  65. data/webpack/components/ApplicationDefinition/index.js +33 -0
  66. data/webpack/components/ApplicationInstance/ApplicationInstance.js +412 -0
  67. data/webpack/components/ApplicationInstance/ApplicationInstance.scss +11 -0
  68. data/webpack/components/ApplicationInstance/ApplicationInstanceActions.js +239 -0
  69. data/webpack/components/ApplicationInstance/ApplicationInstanceConstants.js +14 -0
  70. data/webpack/components/ApplicationInstance/ApplicationInstanceReducer.js +295 -0
  71. data/webpack/components/ApplicationInstance/ApplicationInstanceSelectors.js +9 -0
  72. data/webpack/components/ApplicationInstance/components/AppDefinitionSelector.js +49 -0
  73. data/webpack/components/ApplicationInstance/components/Service.js +30 -0
  74. data/webpack/components/ApplicationInstance/components/ServiceCounter.js +37 -0
  75. data/webpack/components/ApplicationInstance/index.js +35 -0
  76. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReport.js +155 -0
  77. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReport.scss +27 -0
  78. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportActions.js +86 -0
  79. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportConstants.js +4 -0
  80. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportReducer.js +52 -0
  81. data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportSelectors.js +5 -0
  82. data/webpack/components/ApplicationInstanceReport/components/ReportViewer.js +26 -0
  83. data/webpack/components/ApplicationInstanceReport/index.js +27 -0
  84. data/webpack/components/ParameterSelection/ParameterSelection.js +96 -183
  85. data/webpack/components/ParameterSelection/ParameterSelection.scss +10 -3
  86. data/webpack/components/ParameterSelection/ParameterSelectionActions.js +72 -104
  87. data/webpack/components/ParameterSelection/ParameterSelectionConstants.js +14 -19
  88. data/webpack/components/ParameterSelection/ParameterSelectionHelper.js +3 -35
  89. data/webpack/components/ParameterSelection/ParameterSelectionReducer.js +100 -83
  90. data/webpack/components/ParameterSelection/ParameterSelectionSelectors.js +3 -7
  91. data/webpack/components/ParameterSelection/__fixtures__/parameterSelection.fixtures.js +12 -21
  92. data/webpack/components/ParameterSelection/__fixtures__/parameterSelectionData_1.fixtures.js +1 -1
  93. data/webpack/components/ParameterSelection/__fixtures__/parameterSelectionReducer.fixtures.js +3 -45
  94. data/webpack/components/ParameterSelection/__tests__/ParameterSelection.test.js +20 -0
  95. data/webpack/components/ParameterSelection/__tests__/ParameterSelectionReducer.test.js +22 -46
  96. data/webpack/components/ParameterSelection/__tests__/ParameterSelectionSelectors.test.js +6 -6
  97. data/webpack/components/ParameterSelection/__tests__/__snapshots__/ParameterSelection.test.js.snap +40 -265
  98. data/webpack/components/ParameterSelection/__tests__/__snapshots__/ParameterSelectionReducer.test.js.snap +11 -96
  99. data/webpack/components/ParameterSelection/__tests__/__snapshots__/ParameterSelectionSelectors.test.js.snap +3 -9
  100. data/webpack/components/ParameterSelection/index.js +6 -8
  101. data/webpack/components/common/AddTableEntry.js +30 -0
  102. data/webpack/components/common/DeleteTableEntry.js +39 -0
  103. data/webpack/components/common/ExtSelect.js +43 -0
  104. data/webpack/components/common/RailsData.js +27 -0
  105. data/webpack/components/common/__tests__/AddTableEntry.test.js +26 -0
  106. data/webpack/components/common/__tests__/DeleteTableEntry.test.js +29 -0
  107. data/webpack/components/common/__tests__/ExtSelect.test.js +38 -0
  108. data/webpack/components/common/__tests__/RailsData.test.js +16 -0
  109. data/webpack/components/common/__tests__/__snapshots__/AddParameter.test.js.snap +35 -0
  110. data/webpack/components/common/__tests__/__snapshots__/AddTableEntry.test.js.snap +35 -0
  111. data/webpack/components/common/__tests__/__snapshots__/DeleteParameter.test.js.snap +41 -0
  112. data/webpack/components/common/__tests__/__snapshots__/DeleteTableEntry.test.js.snap +41 -0
  113. data/webpack/components/common/__tests__/__snapshots__/ExtSelect.test.js.snap +18 -0
  114. data/webpack/components/common/__tests__/__snapshots__/RailsData.test.js.snap +10 -0
  115. data/webpack/helper.js +20 -0
  116. data/webpack/index.js +6 -0
  117. data/webpack/reducer.js +43 -3
  118. metadata +85 -39
@@ -0,0 +1,8 @@
1
+ const applicationDefinitionConf = state => state.foremanAcd.applicationDefinitionConf;
2
+
3
+ export const selectEditMode = state => applicationDefinitionConf(state).editMode;
4
+ export const selectAnsiblePlaybook = state => applicationDefinitionConf(state).ansiblePlaybook;
5
+ export const selectServices = state => applicationDefinitionConf(state).services;
6
+ export const selectColumns = state => applicationDefinitionConf(state).columns;
7
+ export const selectParametersData = state => applicationDefinitionConf(state).parametersData;
8
+ export const selectAnsibleVarsAll = state => applicationDefinitionConf(state).ansibleVarsAll;
@@ -0,0 +1,49 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import ExtSelect from '../../common/ExtSelect';
4
+ import RailsData from '../../common/RailsData'
5
+
6
+ const AnsiblePlaybookSelector= ({
7
+ label,
8
+ hidden,
9
+ editable,
10
+ viewText,
11
+ selectValue,
12
+ onChange,
13
+ options,
14
+ additionalData,
15
+ }) =>{
16
+ return (
17
+ <div className="form-group">
18
+ <label className="col-md-2 control-label">{label}</label>
19
+ <div className="col-md-4">
20
+ <ExtSelect
21
+ editable={editable}
22
+ viewText={viewText}
23
+ selectValue={selectValue}
24
+ onChange={onChange}
25
+ options={options}
26
+ additionalData={additionalData}
27
+ />
28
+ <RailsData
29
+ key='ansible_playbook_id'
30
+ view='app_definition'
31
+ parameter='acd_ansible_playbook_id'
32
+ value={selectValue}
33
+ />
34
+ </div>
35
+ </div>
36
+ );
37
+ };
38
+
39
+ AnsiblePlaybookSelector.propTypes = {
40
+ label: PropTypes.string.isRequired,
41
+ editable: PropTypes.bool.isRequired,
42
+ viewText: PropTypes.string,
43
+ selectValue: PropTypes.string,
44
+ onChange: PropTypes.func.isRequired,
45
+ options: PropTypes.object,
46
+ additionalData: PropTypes.object,
47
+ };
48
+
49
+ export default AnsiblePlaybookSelector;
@@ -0,0 +1,33 @@
1
+ import { bindActionCreators } from 'redux';
2
+ import { connect } from 'react-redux';
3
+
4
+ import './ApplicationDefinition.scss';
5
+ import ApplicationDefinition from './ApplicationDefinition';
6
+ import * as ApplicationDefinitionActions from './ApplicationDefinitionActions';
7
+
8
+ import {
9
+ selectEditMode,
10
+ selectAnsiblePlaybook,
11
+ selectServices,
12
+ selectColumns,
13
+ selectParametersData,
14
+ selectAnsibleVarsAll,
15
+ } from './ApplicationDefinitionSelectors';
16
+
17
+ const mapStateToProps = state => ({
18
+ editMode: selectEditMode(state),
19
+ ansiblePlaybook: selectAnsiblePlaybook(state),
20
+ services: selectServices(state),
21
+ columns: selectColumns(state),
22
+ parametersData: selectParametersData(state),
23
+ ansibleVarsAll: selectAnsibleVarsAll(state),
24
+ });
25
+
26
+ const mapDispatchToProps = dispatch =>
27
+ bindActionCreators(ApplicationDefinitionActions, dispatch);
28
+
29
+ export default connect(
30
+ mapStateToProps,
31
+ mapDispatchToProps
32
+ )(ApplicationDefinition);
33
+
@@ -0,0 +1,412 @@
1
+ import React, { useState } from 'react'
2
+ import PropTypes from 'prop-types';
3
+ import {
4
+ Icon,
5
+ Button,
6
+ } from 'patternfly-react';
7
+ import * as resolve from 'table-resolver';
8
+ import ForemanModal from 'foremanReact/components/ForemanModal';
9
+ import Select from 'foremanReact/components/common/forms/Select';
10
+ import ParameterSelection from '../ParameterSelection';
11
+ import AddTableEntry from '../common/AddTableEntry';
12
+ import DeleteTableEntry from '../common/DeleteTableEntry';
13
+ import RailsData from '../common/RailsData'
14
+ import AppDefinitionSelector from './components/AppDefinitionSelector';
15
+ import ServiceCounter from './components/ServiceCounter';
16
+ import { arrayToObject } from '../../helper';
17
+
18
+ import {
19
+ Table,
20
+ FormControl,
21
+ inlineEditFormatterFactory,
22
+ } from 'patternfly-react';
23
+
24
+ import {
25
+ PARAMETER_SELECTION_PARAM_TYPE_FOREMAN,
26
+ PARAMETER_SELECTION_PARAM_TYPE_ANSIBLE,
27
+ } from '../ParameterSelection/ParameterSelectionConstants';
28
+
29
+ class ApplicationInstance extends React.Component {
30
+
31
+ constructor(props) {
32
+ super(props);
33
+ }
34
+
35
+ isEditing({rowData}) {
36
+ return (rowData.backup !== undefined);
37
+ }
38
+
39
+ validateParameters() {
40
+ let result = true;
41
+ let msg = "";
42
+
43
+ this.props.hosts.forEach(h => {
44
+ if (h.parameters.map(e => e.value).filter(i => i == "").length > 0) {
45
+ result = false;
46
+
47
+ if (msg == "") {
48
+ msg += "For some hosts the values for some parameters are missing. Check the values for these hosts:\n";
49
+ }
50
+ msg += "- "+ h.hostname +"\n";
51
+ }
52
+ });
53
+
54
+ const invalidMinServices = this.props.services.filter(s => (Number(s.minCount) != 0) && (s.currentCount < s.minCount));
55
+ const invalidMaxServices = this.props.services.filter(s => (Number(s.maxCount) != 0) && (s.currentCount > s.maxCount));
56
+
57
+ if (invalidMinServices.length > 0 || invalidMaxServices.length > 0) {
58
+ result = false;
59
+
60
+ if (msg != "") {
61
+ msg += "\n";
62
+ }
63
+ msg += "Unachieved service counts: \n";
64
+
65
+ invalidMinServices.map(s => { msg += "- service "+ s.name +" expects at least "+ s.minCount +" configured hosts" });
66
+ invalidMaxServices.map(s => { msg += "- service "+ s.name +" expects no more than "+ s.maxCount +" configured hosts" });
67
+ }
68
+
69
+ if (result === false) {
70
+ window.alert(msg);
71
+ }
72
+ return result;
73
+ }
74
+
75
+ componentDidMount() {
76
+ const {
77
+ data: { mode, appDefinition, hosts, ansibleVarsAll, appDefinitionUrl },
78
+ initApplicationInstance,
79
+ addApplicationInstanceHost,
80
+ deleteApplicationInstanceHost,
81
+ activateEditApplicationInstanceHost,
82
+ changeEditApplicationInstanceHost,
83
+ openForemanParameterSelectionModal,
84
+ openAnsibleParameterSelectionModal,
85
+ loadApplicationDefinition,
86
+ } = this.props;
87
+
88
+ if (mode === 'editInstance') {
89
+ loadApplicationDefinition(appDefinition.id, { url: appDefinitionUrl });
90
+ }
91
+
92
+ const inlineEditButtonsFormatter = inlineEditFormatterFactory({
93
+ isEditing: additionalData => this.props.editMode,
94
+ renderValue: (value, additionalData) => (
95
+ <td style={{ padding: '2px' }}>
96
+ <Button
97
+ bsStyle="default"
98
+ onClick={() => activateEditApplicationInstanceHost(additionalData)}
99
+ >
100
+ <Icon type="pf" name="edit" title="edit entry" />
101
+ </Button>
102
+ &nbsp;
103
+ <Button
104
+ bsStyle="default"
105
+ onClick={() => openForemanParameterSelectionModal(additionalData)}
106
+ >
107
+ <Icon type="pf" name="settings" title="change parameters" />
108
+ </Button>
109
+ &nbsp;
110
+ <Button
111
+ bsStyle="default"
112
+ onClick={() => openAnsibleParameterSelectionModal(additionalData)}
113
+ >
114
+ <span title="change ansible variables">A</span>
115
+ </Button>
116
+ <DeleteTableEntry
117
+ hidden={false}
118
+ disabled={false}
119
+ onDeleteTableEntry={deleteApplicationInstanceHost}
120
+ additionalData={additionalData}
121
+ />
122
+ </td>
123
+ ),
124
+ renderEdit: (value, additionalData) => (
125
+ <td style={{ padding: '2px' }}>
126
+ <Button bsStyle="default" disabled>
127
+ <Icon type="pf" name="edit" />
128
+ </Button>
129
+ &nbsp;
130
+ <Button bsStyle="default" disabled>
131
+ <Icon type="pf" name="settings" />
132
+ </Button>
133
+ &nbsp;
134
+ <Button bsStyle="default" disabled>
135
+ <span>A</span>
136
+ </Button>
137
+ <DeleteTableEntry
138
+ hidden={false}
139
+ disabled={true}
140
+ onDeleteTableEntry={deleteApplicationInstanceHost}
141
+ additionalData={additionalData}
142
+ />
143
+ </td>
144
+ )
145
+ });
146
+ this.inlineEditButtonsFormatter = inlineEditButtonsFormatter;
147
+
148
+ const headerFormatter = value => <Table.Heading>{value}</Table.Heading>;
149
+ this.headerFormatter = headerFormatter;
150
+
151
+ const inlineEditFormatterImpl = {
152
+ renderValue: (value, additionalData) => (
153
+ <td>
154
+ <span className="static">{value}</span>
155
+ </td>
156
+ ),
157
+ renderEditText: (value, additionalData, subtype='text') => (
158
+ <td className="editing">
159
+ <FormControl
160
+ type={subtype}
161
+ defaultValue={value}
162
+ onBlur={e => changeEditApplicationInstanceHost(e.target.value, additionalData) }
163
+ />
164
+ </td>
165
+ ),
166
+ renderEditSelect: (value, additionalData, options) => (
167
+ <td className="editing">
168
+ <Select
169
+ value={value.toString()}
170
+ onChange={e => changeEditApplicationInstanceHost(e.target.value, additionalData) }
171
+ options={options}
172
+ allowClear
173
+ key="key"
174
+ />
175
+ </td>
176
+ )
177
+ };
178
+
179
+ const inlineEditFormatter = inlineEditFormatterFactory({
180
+ isEditing: additionalData => this.isEditing(additionalData),
181
+ renderValue: (value, additionalData) => {
182
+ let prettyValue = value;
183
+ if (additionalData.property == 'service') {
184
+ const serviceList = arrayToObject(this.props.services, "id", "name");
185
+ prettyValue = serviceList[value];
186
+ }
187
+ return inlineEditFormatterImpl.renderValue(prettyValue, additionalData)
188
+ },
189
+ renderEdit: (value, additionalData) => {
190
+ let prettyValue = value;
191
+ if (additionalData.property == 'service') {
192
+ const availableServices = this.props.services.filter(service => ((Number(service['maxCount']) == 0) || (service['currentCount'] < service['maxCount'])));
193
+ const serviceList = arrayToObject(availableServices, "id", "name");
194
+
195
+ if (additionalData.rowData.newEntry === true) {
196
+ return inlineEditFormatterImpl.renderEditSelect(value, additionalData, serviceList);
197
+ }
198
+ prettyValue = serviceList[value];
199
+ return inlineEditFormatterImpl.renderValue(prettyValue, additionalData)
200
+ }
201
+ return inlineEditFormatterImpl.renderEditText(prettyValue, additionalData);
202
+ }
203
+ });
204
+ this.inlineEditFormatter = inlineEditFormatter;
205
+
206
+ initApplicationInstance(
207
+ appDefinition,
208
+ hosts,
209
+ ansibleVarsAll,
210
+ this.headerFormatter,
211
+ this.inlineEditFormatter,
212
+ this.inlineEditButtonsFormatter,
213
+ );
214
+ };
215
+
216
+ render() {
217
+ const {
218
+ data: { mode, applications, organization, location, foremanDataUrl, appDefinitionUrl },
219
+ appDefinition,
220
+ services,
221
+ hosts,
222
+ columns,
223
+ addApplicationInstanceHost,
224
+ confirmEditApplicationInstanceHost,
225
+ cancelEditApplicationInstanceHost,
226
+ closeForemanParameterSelectionModal,
227
+ openAnsibleParameterSelectionModal,
228
+ closeAnsibleParameterSelectionModal,
229
+ loadApplicationDefinition,
230
+ } = this.props;
231
+
232
+ // Start from validation when pressing submit. This should be in componentDidMount() but
233
+ // unfortunatley then the event wasn't fired. To make sure, that the on-click is only added
234
+ // once, there is a workaround to check if a css class "bound" exists.
235
+ $('input[type="submit"][name="commit"]:not(.bound)').addClass('bound').on('click', () => this.validateParameters());
236
+
237
+ return (
238
+ <span>
239
+ <div class="service-counter">
240
+ <ServiceCounter
241
+ title="Service counts"
242
+ serviceList={ services }
243
+ hostList={ hosts }
244
+ />
245
+ </div>
246
+ <div>
247
+ <AppDefinitionSelector
248
+ label="Application Definition"
249
+ editable={ mode == 'newInstance' }
250
+ viewText={ appDefinition.name }
251
+ options={ applications }
252
+ onChange={ loadApplicationDefinition }
253
+ selectValue={ appDefinition.id.toString() }
254
+ additionalData={{url: appDefinitionUrl}}
255
+ />
256
+ </div>
257
+ <div className="form-group">
258
+ <AddTableEntry
259
+ hidden={ false }
260
+ disabled={ this.props.editMode }
261
+ onAddTableEntry={ addApplicationInstanceHost }
262
+ />
263
+ <Table.PfProvider
264
+ striped
265
+ bordered
266
+ hover
267
+ dataTable
268
+ inlineEdit
269
+ columns={columns}
270
+ components={{
271
+ body: {
272
+ row: Table.InlineEditRow,
273
+ cell: cellProps => cellProps.children
274
+ }
275
+ }}
276
+ >
277
+ <Table.Header headerRows={resolve.headerRows({ columns })} />
278
+ <Table.Body
279
+ rows={hosts}
280
+ rowKey="id"
281
+ onRow={(rowData, { rowIndex }) => ({
282
+ role: 'row',
283
+ isEditing: () => this.isEditing({ rowData }),
284
+ onCancel: () => cancelEditApplicationInstanceHost({ rowData, rowIndex }),
285
+ onConfirm: () => confirmEditApplicationInstanceHost({ rowData, rowIndex }),
286
+ last: rowIndex === services.length - 1
287
+ })}
288
+ />
289
+ </Table.PfProvider>
290
+ <AddTableEntry
291
+ hidden={ false }
292
+ disabled={ this.props.editMode }
293
+ onAddTableEntry={ addApplicationInstanceHost }
294
+ />
295
+ <span style={{ marginLeft: 30 }}>
296
+ Ansible group vars 'all':
297
+ <Button
298
+ style={{ marginLeft: 10 }}
299
+ bsStyle="default"
300
+ disabled={ this.props.editMode }
301
+ onClick={() => openAnsibleParameterSelectionModal({
302
+ isAllGroup: true
303
+ })}
304
+ >
305
+ <span title="change ansible variables for 'all'">A</span>
306
+ </Button>
307
+ </span>
308
+ </div>
309
+ <div>
310
+ <ForemanModal
311
+ id="AppInstanceForemanParamSelection"
312
+ dialogClassName="param_selection_modal"
313
+ title="Foreman Parameter specification for Application Instance"
314
+ >
315
+ <ForemanModal.Header closeButton={false}>
316
+ Parameter specification
317
+ </ForemanModal.Header>
318
+ {this.props.parametersData ? (
319
+ <ParameterSelection
320
+ paramType={ PARAMETER_SELECTION_PARAM_TYPE_FOREMAN }
321
+ location={ location }
322
+ organization={ organization }
323
+ paramDataUrl= { foremanDataUrl }
324
+ data={ this.props.parametersData }
325
+ />
326
+ ) : (<span>Empty</span>)
327
+ }
328
+ <ForemanModal.Footer>
329
+ <div>
330
+ <Button bsStyle="primary" onClick={() => closeForemanParameterSelectionModal({ mode: 'save' })}>Save</Button>
331
+ <Button bsStyle="default" onClick={() => closeForemanParameterSelectionModal({ mode: 'cancel' })}>Cancel</Button>
332
+ </div>
333
+ </ForemanModal.Footer>
334
+ </ForemanModal>
335
+ </div>
336
+ <div>
337
+ <ForemanModal
338
+ id="AppInstanceAnsibleParamSelection"
339
+ dialogClassName="param_selection_modal"
340
+ title="Ansible group variables for Application Instance"
341
+ >
342
+ <ForemanModal.Header closeButton={false}>
343
+ Parameter specification
344
+ </ForemanModal.Header>
345
+ {this.props.parametersData ? (
346
+ <ParameterSelection
347
+ paramType={ PARAMETER_SELECTION_PARAM_TYPE_ANSIBLE }
348
+ location={ location }
349
+ organization={ organization }
350
+ data={ this.props.parametersData }
351
+ />
352
+ ) : (<span>Empty</span>)
353
+ }
354
+ <ForemanModal.Footer>
355
+ <div>
356
+ <Button bsStyle="primary" onClick={() => closeAnsibleParameterSelectionModal({ mode: 'save' })}>Save</Button>
357
+ <Button bsStyle="default" onClick={() => closeAnsibleParameterSelectionModal({ mode: 'cancel' })}>Cancel</Button>
358
+ </div>
359
+ </ForemanModal.Footer>
360
+ </ForemanModal>
361
+ </div>
362
+ <RailsData
363
+ key='applications_instance'
364
+ view='app_instance'
365
+ parameter='hosts'
366
+ value={JSON.stringify(this.props.hosts)}
367
+ />
368
+ <RailsData
369
+ key='applications_instance'
370
+ view='app_instance'
371
+ parameter='ansible_vars_all'
372
+ value={JSON.stringify(this.props.ansibleVarsAll)}
373
+ />
374
+ </span>
375
+ )};
376
+ }
377
+
378
+ ApplicationInstance.defaultProps = {
379
+ error: {},
380
+ appDefinition: { "id": '', "name": '' },
381
+ editMode: false,
382
+ services: [],
383
+ hosts: [],
384
+ ansibleVarsAll: [],
385
+ parametersData: {},
386
+ columns: [],
387
+ editParamsOfRowId: null,
388
+ }
389
+
390
+ ApplicationInstance.propTypes = {
391
+ initApplicationInstance: PropTypes.func,
392
+ editMode: PropTypes.bool.isRequired,
393
+ services: PropTypes.array,
394
+ appDefinition: PropTypes.object,
395
+ columns: PropTypes.array,
396
+ hosts: PropTypes.array,
397
+ ansibleVarsAll: PropTypes.array,
398
+ loadApplicationDefinition: PropTypes.func,
399
+ addApplicationInstanceHost: PropTypes.func,
400
+ deleteApplicationInstanceHost: PropTypes.func,
401
+ activateEditApplicationInstanceHost: PropTypes.func,
402
+ confirmEditApplicationInstanceHost: PropTypes.func,
403
+ cancelEditApplicationInstanceHost: PropTypes.func,
404
+ changeEditApplicationInstanceHost: PropTypes.func,
405
+ openForemanParameterSelectionModal: PropTypes.func,
406
+ closeForemanParameterSelectionModal: PropTypes.func,
407
+ openAnsibleParameterSelectionModal: PropTypes.func,
408
+ closeAnsibleParameterSelectionModal: PropTypes.func,
409
+ parametersData: PropTypes.object,
410
+ };
411
+
412
+ export default ApplicationInstance;