foreman_acd 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +82 -86
- data/app/controllers/foreman_acd/ansible_playbooks_controller.rb +13 -11
- data/app/controllers/foreman_acd/api/v2/ansible_playbooks_controller.rb +4 -3
- data/app/controllers/foreman_acd/api/v2/app_definitions_controller.rb +1 -0
- data/app/controllers/foreman_acd/api/v2/app_instances_controller.rb +9 -1
- data/app/controllers/foreman_acd/app_definitions_controller.rb +14 -9
- data/app/controllers/foreman_acd/app_instances_controller.rb +97 -25
- data/app/controllers/foreman_acd/concerns/ansible_playbook_parameters.rb +1 -1
- data/app/controllers/foreman_acd/concerns/app_definition_parameters.rb +1 -1
- data/app/controllers/foreman_acd/concerns/app_instance_parameters.rb +1 -1
- data/app/controllers/foreman_acd/remote_execution_controller.rb +3 -6
- data/app/controllers/ui_acd_controller.rb +9 -0
- data/app/lib/actions/foreman_acd/deploy_all_hosts.rb +42 -0
- data/app/lib/actions/foreman_acd/run_configurator.rb +41 -0
- data/app/models/concerns/foreman_acd/host_managed_extensions.rb +51 -0
- data/app/models/foreman_acd/acd_provider.rb +3 -0
- data/app/models/foreman_acd/ansible_playbook.rb +30 -13
- data/app/models/foreman_acd/app_definition.rb +24 -1
- data/app/models/foreman_acd/app_instance.rb +40 -5
- data/app/models/foreman_acd/foreman_host.rb +23 -0
- data/app/models/foreman_acd/taxonomy_extensions.rb +17 -0
- data/app/services/foreman_acd/app_configurator.rb +7 -10
- data/app/services/foreman_acd/app_deployer.rb +59 -47
- data/app/services/foreman_acd/inventory_creator.rb +12 -25
- data/app/views/foreman_acd/ansible_playbooks/_form.html.erb +11 -2
- data/app/views/foreman_acd/ansible_playbooks/edit.html.erb +9 -1
- data/app/views/foreman_acd/ansible_playbooks/index.html.erb +3 -3
- data/app/views/foreman_acd/api/v2/ansible_playbooks/base.json.rabl +2 -0
- data/app/views/foreman_acd/api/v2/ansible_playbooks/index.json.rabl +2 -0
- data/app/views/foreman_acd/api/v2/ansible_playbooks/show.json.rabl +6 -0
- data/app/views/foreman_acd/api/v2/app_definitions/base.json.rabl +2 -0
- data/app/views/foreman_acd/api/v2/app_definitions/index.json.rabl +2 -0
- data/app/views/foreman_acd/api/v2/app_definitions/show.json.rabl +6 -0
- data/app/views/foreman_acd/api/v2/app_instances/base.json.rabl +3 -1
- data/app/views/foreman_acd/api/v2/app_instances/index.json.rabl +2 -0
- data/app/views/foreman_acd/api/v2/app_instances/show.json.rabl +2 -0
- data/app/views/foreman_acd/app_definitions/_form.html.erb +8 -0
- data/app/views/foreman_acd/app_definitions/edit.html.erb +10 -5
- data/app/views/foreman_acd/app_definitions/index.html.erb +4 -4
- data/app/views/foreman_acd/app_instances/_form.html.erb +3 -3
- data/app/views/foreman_acd/app_instances/edit.html.erb +10 -0
- data/app/views/foreman_acd/app_instances/index.html.erb +87 -14
- data/app/views/foreman_acd/app_instances/report.html.erb +5 -2
- data/app/views/templates/job/run_acd_ansible_playbook.erb +14 -1
- data/app/views/ui_acd/app_definition.json.rabl +1 -1
- data/config/routes.rb +1 -2
- data/db/migrate/20200917120220_add_ansible_playbook_id.rb +1 -1
- data/db/migrate/20201016002819_add_ansible_vars_all_to_app_definitions.rb +3 -0
- data/db/migrate/20201016104338_add_ansible_vars_all_to_app_instances.rb +3 -0
- data/db/migrate/20210112111548_add_organization_to_app_instance.rb +22 -0
- data/db/migrate/20210112113853_add_location_to_app_instance.rb +8 -0
- data/db/migrate/20210202141658_create_foreman_hosts.rb +24 -0
- data/db/migrate/20210204111306_remove_hosts_from_app_instances.rb +8 -0
- data/db/migrate/20210209091014_rename_acd_tables.rb +16 -0
- data/db/migrate/20210216083522_add_last_progress_report.rb +8 -0
- data/db/migrate/20210216091529_add_last_deploy_task.rb +8 -0
- data/db/seeds.d/62_acd_proxy_feature.rb +1 -3
- data/db/seeds.d/75-job_templates.rb +6 -1
- data/lib/foreman_acd/engine.rb +14 -3
- data/lib/foreman_acd/plugin.rb +49 -28
- data/lib/foreman_acd/version.rb +1 -1
- data/locale/en/foreman_acd.edit.po +326 -0
- data/locale/en/foreman_acd.po +232 -2
- data/{app/controllers/foreman_acd/api/v2/app_playbooks_controller.rb → locale/en/foreman_acd.po.time_stamp} +0 -0
- data/locale/foreman_acd.pot +343 -8
- data/test/controllers/ansible_playbooks_controller_test.rb +27 -0
- data/webpack/components/ApplicationDefinition/ApplicationDefinition.js +31 -18
- data/webpack/components/ApplicationDefinition/ApplicationDefinitionActions.js +8 -0
- data/webpack/components/ApplicationDefinition/ApplicationDefinitionConstants.js +1 -0
- data/webpack/components/ApplicationDefinition/ApplicationDefinitionReducer.js +26 -0
- data/webpack/components/ApplicationDefinition/ApplicationDefinitionSelectors.js +1 -0
- data/webpack/components/ApplicationDefinition/index.js +2 -0
- data/webpack/components/ApplicationInstance/ApplicationInstance.js +67 -30
- data/webpack/components/ApplicationInstance/ApplicationInstanceActions.js +8 -0
- data/webpack/components/ApplicationInstance/ApplicationInstanceConstants.js +1 -0
- data/webpack/components/ApplicationInstance/ApplicationInstanceReducer.js +16 -2
- data/webpack/components/ApplicationInstance/ApplicationInstanceSelectors.js +1 -0
- data/webpack/components/ApplicationInstance/components/Service.js +1 -1
- data/webpack/components/ApplicationInstance/index.js +2 -0
- data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReport.js +53 -60
- data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReport.scss +17 -0
- data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportActions.js +7 -51
- data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportConstants.js +2 -4
- data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportReducer.js +4 -18
- data/webpack/components/ApplicationInstanceReport/ApplicationInstanceReportSelectors.js +0 -1
- data/webpack/components/ApplicationInstanceReport/components/ReportViewer.js +1 -1
- data/webpack/components/ApplicationInstanceReport/index.js +0 -2
- data/webpack/components/ParameterSelection/ParameterSelection.js +10 -0
- data/webpack/components/ParameterSelection/ParameterSelectionActions.js +8 -7
- data/webpack/components/common/DeleteTableEntry.js +3 -2
- data/webpack/components/common/EditTableEntry.js +2 -1
- data/webpack/components/common/LockTableEntry.js +2 -1
- metadata +48 -6
- data/app/views/foreman_acd/app_instances/deploy.html.erb +0 -19
@@ -30,6 +30,7 @@ import {
|
|
30
30
|
APPLICATION_DEFINITION_FOREMAN_PARAMETER_SELECTION_MODAL_CLOSE,
|
31
31
|
APPLICATION_DEFINITION_ANSIBLE_PARAMETER_SELECTION_MODAL_OPEN,
|
32
32
|
APPLICATION_DEFINITION_ANSIBLE_PARAMETER_SELECTION_MODAL_CLOSE,
|
33
|
+
APPLICATION_DEFINITION_CHANGE_PARAMETER_SELECTION_MODE,
|
33
34
|
} from './ApplicationDefinitionConstants';
|
34
35
|
|
35
36
|
import {
|
@@ -293,3 +294,10 @@ export const closeAnsibleParameterSelectionModal = (additionalData) => dispatch
|
|
293
294
|
setModalClosed({ id: 'AppDefinitionAnsibleParamSelection' })
|
294
295
|
);
|
295
296
|
}
|
297
|
+
|
298
|
+
export const changeParameterSelectionMode = (additionalData) => ({
|
299
|
+
type: APPLICATION_DEFINITION_CHANGE_PARAMETER_SELECTION_MODE,
|
300
|
+
payload: {
|
301
|
+
...additionalData,
|
302
|
+
},
|
303
|
+
})
|
@@ -12,3 +12,4 @@ export const APPLICATION_DEFINITION_FOREMAN_PARAMETER_SELECTION_MODAL_OPEN = 'AP
|
|
12
12
|
export const APPLICATION_DEFINITION_FOREMAN_PARAMETER_SELECTION_MODAL_CLOSE = 'APPLICATION_DEFINITION_FOREMAN_PARAMETER_SELECTION_MODAL_CLOSE';
|
13
13
|
export const APPLICATION_DEFINITION_ANSIBLE_PARAMETER_SELECTION_MODAL_OPEN = 'APPLICATION_DEFINITION_ANSIBLE_PARAMETER_SELECTION_MODAL_OPEN';
|
14
14
|
export const APPLICATION_DEFINITION_ANSIBLE_PARAMETER_SELECTION_MODAL_CLOSE = 'APPLICATION_DEFINITION_ANSIBLE_PARAMETER_SELECTION_MODAL_CLOSE';
|
15
|
+
export const APPLICATION_DEFINITION_CHANGE_PARAMETER_SELECTION_MODE = 'APPLICATION_DEFINITION_CHANGE_PARAMETER_SELECTION_MODE';
|
@@ -21,6 +21,7 @@ import {
|
|
21
21
|
APPLICATION_DEFINITION_FOREMAN_PARAMETER_SELECTION_MODAL_CLOSE,
|
22
22
|
APPLICATION_DEFINITION_ANSIBLE_PARAMETER_SELECTION_MODAL_OPEN,
|
23
23
|
APPLICATION_DEFINITION_ANSIBLE_PARAMETER_SELECTION_MODAL_CLOSE,
|
24
|
+
APPLICATION_DEFINITION_CHANGE_PARAMETER_SELECTION_MODE,
|
24
25
|
} from './ApplicationDefinitionConstants';
|
25
26
|
|
26
27
|
import {
|
@@ -109,6 +110,28 @@ const applicationDefinitionConf = (state = initialState, action) => {
|
|
109
110
|
const services = cloneDeep(state.services);
|
110
111
|
const index = findIndex(services, { id: payload.rowData.id });
|
111
112
|
|
113
|
+
const thisService = services[index];
|
114
|
+
|
115
|
+
if (thisService.name == '') {
|
116
|
+
window.alert("Every service needs to have a valid name.");
|
117
|
+
return state;
|
118
|
+
}
|
119
|
+
|
120
|
+
if (thisService.hostgroup == '') {
|
121
|
+
window.alert("Every service needs to be assigned to a hostgroup.");
|
122
|
+
return state;
|
123
|
+
}
|
124
|
+
|
125
|
+
if (thisService.ansibleGroup == '') {
|
126
|
+
window.alert("Every service needs to be assigned to a ansible group.");
|
127
|
+
return state;
|
128
|
+
}
|
129
|
+
|
130
|
+
if (state.services.filter(v => v.name === thisService.name && v.id != thisService.id).length > 0) {
|
131
|
+
window.alert("Service name already used in this Application Definition. Please make sure that every service name is unique.");
|
132
|
+
return state;
|
133
|
+
}
|
134
|
+
|
112
135
|
delete services[index].backup;
|
113
136
|
delete services[index].newEntry;
|
114
137
|
|
@@ -235,6 +258,9 @@ const applicationDefinitionConf = (state = initialState, action) => {
|
|
235
258
|
}
|
236
259
|
return state.merge(newState);
|
237
260
|
}
|
261
|
+
case APPLICATION_DEFINITION_CHANGE_PARAMETER_SELECTION_MODE: {
|
262
|
+
return state.merge({ paramEditMode: payload.mode });
|
263
|
+
}
|
238
264
|
default:
|
239
265
|
return state;
|
240
266
|
}
|
@@ -6,3 +6,4 @@ export const selectServices = state => applicationDefinitionConf(state).services
|
|
6
6
|
export const selectColumns = state => applicationDefinitionConf(state).columns;
|
7
7
|
export const selectParametersData = state => applicationDefinitionConf(state).parametersData;
|
8
8
|
export const selectAnsibleVarsAll = state => applicationDefinitionConf(state).ansibleVarsAll;
|
9
|
+
export const selectParamEditMode = state => applicationDefinitionConf(state).paramEditMode;
|
@@ -12,6 +12,7 @@ import {
|
|
12
12
|
selectColumns,
|
13
13
|
selectParametersData,
|
14
14
|
selectAnsibleVarsAll,
|
15
|
+
selectParamEditMode,
|
15
16
|
} from './ApplicationDefinitionSelectors';
|
16
17
|
|
17
18
|
const mapStateToProps = state => ({
|
@@ -21,6 +22,7 @@ const mapStateToProps = state => ({
|
|
21
22
|
columns: selectColumns(state),
|
22
23
|
parametersData: selectParametersData(state),
|
23
24
|
ansibleVarsAll: selectAnsibleVarsAll(state),
|
25
|
+
paramEditMode: selectParamEditMode(state),
|
24
26
|
});
|
25
27
|
|
26
28
|
const mapDispatchToProps = dispatch =>
|
@@ -6,6 +6,10 @@ import {
|
|
6
6
|
} from 'patternfly-react';
|
7
7
|
import * as resolve from 'table-resolver';
|
8
8
|
import ForemanModal from 'foremanReact/components/ForemanModal';
|
9
|
+
import {
|
10
|
+
sprintf,
|
11
|
+
translate as __
|
12
|
+
} from 'foremanReact/common/I18n';
|
9
13
|
import Select from 'foremanReact/components/common/forms/Select';
|
10
14
|
import ParameterSelection from '../ParameterSelection';
|
11
15
|
import AddTableEntry from '../common/AddTableEntry';
|
@@ -37,16 +41,20 @@ class ApplicationInstance extends React.Component {
|
|
37
41
|
return (rowData.backup !== undefined);
|
38
42
|
}
|
39
43
|
|
44
|
+
addTableEntryAllowed() {
|
45
|
+
return this.props.editMode || this.props.appDefinition.id == ''
|
46
|
+
}
|
47
|
+
|
40
48
|
validateParameters() {
|
41
49
|
let result = true;
|
42
50
|
let msg = "";
|
43
51
|
|
44
52
|
this.props.hosts.forEach(h => {
|
45
|
-
if (h.
|
53
|
+
if (h.foremanParameters.map(e => e.value).filter(i => i == "").length > 0) {
|
46
54
|
result = false;
|
47
55
|
|
48
56
|
if (msg == "") {
|
49
|
-
msg += "For some hosts the values for some parameters are missing. Check the values for these hosts:\n";
|
57
|
+
msg += __("For some hosts the values for some parameters are missing. Check the values for these hosts:\n");
|
50
58
|
}
|
51
59
|
msg += "- "+ h.hostname +"\n";
|
52
60
|
}
|
@@ -55,22 +63,31 @@ class ApplicationInstance extends React.Component {
|
|
55
63
|
const invalidMinServices = this.props.services.filter(s => (Number(s.minCount) != 0) && (s.currentCount < s.minCount));
|
56
64
|
const invalidMaxServices = this.props.services.filter(s => (Number(s.maxCount) != 0) && (s.currentCount > s.maxCount));
|
57
65
|
|
66
|
+
console.log(invalidMinServices);
|
67
|
+
|
58
68
|
if (invalidMinServices.length > 0 || invalidMaxServices.length > 0) {
|
59
69
|
result = false;
|
60
70
|
|
61
71
|
if (msg != "") {
|
62
72
|
msg += "\n";
|
63
73
|
}
|
64
|
-
msg += "Unachieved service counts: \n";
|
65
74
|
|
66
|
-
|
67
|
-
|
75
|
+
msg += __("Unachieved service counts:");
|
76
|
+
msg += "\n";
|
77
|
+
|
78
|
+
invalidMinServices.map(s => { msg += sprintf(
|
79
|
+
__(`- service ${s.name} expects at ${s.minCount} least configured hosts\n`)
|
80
|
+
)});
|
81
|
+
|
82
|
+
invalidMaxServices.map(s => { msg += sprintf(
|
83
|
+
__(`- service ${s.name} expects no more than ${s.axCount} configured hosts\n`)
|
84
|
+
)});
|
68
85
|
}
|
69
86
|
|
70
|
-
|
71
|
-
|
87
|
+
return {
|
88
|
+
validateResult: result,
|
89
|
+
validateMsg: msg
|
72
90
|
}
|
73
|
-
return result;
|
74
91
|
}
|
75
92
|
|
76
93
|
componentDidMount() {
|
@@ -98,21 +115,21 @@ class ApplicationInstance extends React.Component {
|
|
98
115
|
bsStyle="default"
|
99
116
|
onClick={() => activateEditApplicationInstanceHost(additionalData)}
|
100
117
|
>
|
101
|
-
<Icon type="pf" name="edit" title="edit entry" />
|
118
|
+
<Icon type="pf" name="edit" title={__("edit entry")} />
|
102
119
|
</Button>
|
103
120
|
|
104
121
|
<Button
|
105
122
|
bsStyle="default"
|
106
123
|
onClick={() => openForemanParameterSelectionModal(additionalData)}
|
107
124
|
>
|
108
|
-
<Icon type="pf" name="settings" title="change parameters" />
|
125
|
+
<Icon type="pf" name="settings" title={__("change parameters")} />
|
109
126
|
</Button>
|
110
127
|
|
111
128
|
<Button
|
112
129
|
bsStyle="default"
|
113
130
|
onClick={() => openAnsibleParameterSelectionModal(additionalData)}
|
114
131
|
>
|
115
|
-
<span title="change ansible variables">A</span>
|
132
|
+
<span title={__("change ansible variables")}>A</span>
|
116
133
|
</Button>
|
117
134
|
|
118
135
|
<DeleteTableEntry
|
@@ -126,11 +143,11 @@ class ApplicationInstance extends React.Component {
|
|
126
143
|
renderEdit: (value, additionalData) => (
|
127
144
|
<td style={{ padding: '2px' }}>
|
128
145
|
<Button bsStyle="default" disabled>
|
129
|
-
<Icon type="pf" name="edit" />
|
146
|
+
<Icon type="pf" name={__("edit")} />
|
130
147
|
</Button>
|
131
148
|
|
132
149
|
<Button bsStyle="default" disabled>
|
133
|
-
<Icon type="pf" name="settings" />
|
150
|
+
<Icon type="pf" name={__("settings")} />
|
134
151
|
</Button>
|
135
152
|
|
136
153
|
<Button bsStyle="default" disabled>
|
@@ -200,6 +217,12 @@ class ApplicationInstance extends React.Component {
|
|
200
217
|
prettyValue = serviceList[value];
|
201
218
|
return inlineEditFormatterImpl.renderValue(prettyValue, additionalData)
|
202
219
|
}
|
220
|
+
if (additionalData.property == 'hostname') {
|
221
|
+
if (additionalData.rowData.newEntry === true) {
|
222
|
+
return inlineEditFormatterImpl.renderEditText(value, additionalData);
|
223
|
+
}
|
224
|
+
return inlineEditFormatterImpl.renderValue(prettyValue, additionalData)
|
225
|
+
}
|
203
226
|
return inlineEditFormatterImpl.renderEditText(prettyValue, additionalData);
|
204
227
|
}
|
205
228
|
});
|
@@ -228,13 +251,17 @@ class ApplicationInstance extends React.Component {
|
|
228
251
|
closeForemanParameterSelectionModal,
|
229
252
|
openAnsibleParameterSelectionModal,
|
230
253
|
closeAnsibleParameterSelectionModal,
|
254
|
+
changeParameterSelectionMode,
|
231
255
|
loadApplicationDefinition,
|
232
256
|
} = this.props;
|
233
257
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
258
|
+
let { validateResult, validateMsg } = this.validateParameters();
|
259
|
+
|
260
|
+
if (validateResult == false) {
|
261
|
+
$('input[type="submit"][name="commit"]').attr("disabled", true);
|
262
|
+
} else {
|
263
|
+
$('input[type="submit"][name="commit"]').attr("disabled", false);
|
264
|
+
}
|
238
265
|
|
239
266
|
return (
|
240
267
|
<span>
|
@@ -255,13 +282,13 @@ class ApplicationInstance extends React.Component {
|
|
255
282
|
selectValue={ appDefinition.id.toString() }
|
256
283
|
additionalData={{url: appDefinitionUrl}}
|
257
284
|
/>
|
285
|
+
{appDefinition.id == '' ? (
|
286
|
+
<p style={{ paddingTop: 25 }}>
|
287
|
+
<pre>{ "App Definition can't be blank" }</pre>
|
288
|
+
</p>
|
289
|
+
) : (<div></div>)}
|
258
290
|
</div>
|
259
291
|
<div className="form-group">
|
260
|
-
<AddTableEntry
|
261
|
-
hidden={ false }
|
262
|
-
disabled={ this.props.editMode }
|
263
|
-
onAddTableEntry={ addApplicationInstanceHost }
|
264
|
-
/>
|
265
292
|
<Table.PfProvider
|
266
293
|
striped
|
267
294
|
bordered
|
@@ -291,7 +318,7 @@ class ApplicationInstance extends React.Component {
|
|
291
318
|
</Table.PfProvider>
|
292
319
|
<AddTableEntry
|
293
320
|
hidden={ false }
|
294
|
-
disabled={ this.
|
321
|
+
disabled={ this.addTableEntryAllowed() }
|
295
322
|
onAddTableEntry={ addApplicationInstanceHost }
|
296
323
|
/>
|
297
324
|
<span style={{ marginLeft: 30 }}>
|
@@ -304,7 +331,7 @@ class ApplicationInstance extends React.Component {
|
|
304
331
|
isAllGroup: true
|
305
332
|
})}
|
306
333
|
>
|
307
|
-
<span title="change ansible variables for 'all'">A</span>
|
334
|
+
<span title={__("change ansible variables for 'all'")}>A</span>
|
308
335
|
</Button>
|
309
336
|
</span>
|
310
337
|
</div>
|
@@ -312,13 +339,14 @@ class ApplicationInstance extends React.Component {
|
|
312
339
|
<ForemanModal
|
313
340
|
id="AppInstanceForemanParamSelection"
|
314
341
|
dialogClassName="param_selection_modal"
|
315
|
-
title="Foreman Parameter specification for Application Instance"
|
342
|
+
title={__("Foreman Parameter specification for Application Instance")}
|
316
343
|
>
|
317
344
|
<ForemanModal.Header closeButton={false}>
|
318
345
|
Parameter specification
|
319
346
|
</ForemanModal.Header>
|
320
347
|
{this.props.parametersData ? (
|
321
348
|
<ParameterSelection
|
349
|
+
editModeCallback={ (hide) => changeParameterSelectionMode({ mode: hide })}
|
322
350
|
paramType={ PARAMETER_SELECTION_PARAM_TYPE_FOREMAN }
|
323
351
|
location={ location }
|
324
352
|
organization={ organization }
|
@@ -329,8 +357,8 @@ class ApplicationInstance extends React.Component {
|
|
329
357
|
}
|
330
358
|
<ForemanModal.Footer>
|
331
359
|
<div>
|
332
|
-
<Button bsStyle="primary" onClick={() => closeForemanParameterSelectionModal({ mode: 'save' })}>Save</Button>
|
333
|
-
<Button bsStyle="default" onClick={() => closeForemanParameterSelectionModal({ mode: 'cancel' })}>Cancel</Button>
|
360
|
+
<Button bsStyle="primary" disabled={this.props.paramEditMode} onClick={() => closeForemanParameterSelectionModal({ mode: 'save' })}>{__("Save")}</Button>
|
361
|
+
<Button bsStyle="default" disabled={this.props.paramEditMode} onClick={() => closeForemanParameterSelectionModal({ mode: 'cancel' })}>{__("Cancel")}</Button>
|
334
362
|
</div>
|
335
363
|
</ForemanModal.Footer>
|
336
364
|
</ForemanModal>
|
@@ -339,13 +367,14 @@ class ApplicationInstance extends React.Component {
|
|
339
367
|
<ForemanModal
|
340
368
|
id="AppInstanceAnsibleParamSelection"
|
341
369
|
dialogClassName="param_selection_modal"
|
342
|
-
title="Ansible group variables for Application Instance"
|
370
|
+
title={__("Ansible group variables for Application Instance")}
|
343
371
|
>
|
344
372
|
<ForemanModal.Header closeButton={false}>
|
345
373
|
Parameter specification
|
346
374
|
</ForemanModal.Header>
|
347
375
|
{this.props.parametersData ? (
|
348
376
|
<ParameterSelection
|
377
|
+
editModeCallback={ (hide) => changeParameterSelectionMode({ mode: hide })}
|
349
378
|
paramType={ PARAMETER_SELECTION_PARAM_TYPE_ANSIBLE }
|
350
379
|
location={ location }
|
351
380
|
organization={ organization }
|
@@ -355,12 +384,17 @@ class ApplicationInstance extends React.Component {
|
|
355
384
|
}
|
356
385
|
<ForemanModal.Footer>
|
357
386
|
<div>
|
358
|
-
<Button bsStyle="primary" onClick={() => closeAnsibleParameterSelectionModal({ mode: 'save' })}>Save</Button>
|
359
|
-
<Button bsStyle="default" onClick={() => closeAnsibleParameterSelectionModal({ mode: 'cancel' })}>Cancel</Button>
|
387
|
+
<Button bsStyle="primary" disabled={this.props.paramEditMode} onClick={() => closeAnsibleParameterSelectionModal({ mode: 'save' })}>{__("Save")}</Button>
|
388
|
+
<Button bsStyle="default" disabled={this.props.paramEditMode} onClick={() => closeAnsibleParameterSelectionModal({ mode: 'cancel' })}>{__("Cancel")}</Button>
|
360
389
|
</div>
|
361
390
|
</ForemanModal.Footer>
|
362
391
|
</ForemanModal>
|
363
392
|
</div>
|
393
|
+
{validateResult == false ? (
|
394
|
+
<p style={{ paddingTop: 25 }}>
|
395
|
+
<pre>{ validateMsg }</pre>
|
396
|
+
</p>
|
397
|
+
) : (<div></div>)}
|
364
398
|
<RailsData
|
365
399
|
key='applications_instance'
|
366
400
|
view='app_instance'
|
@@ -387,6 +421,7 @@ ApplicationInstance.defaultProps = {
|
|
387
421
|
parametersData: {},
|
388
422
|
columns: [],
|
389
423
|
editParamsOfRowId: null,
|
424
|
+
paramEditMode: false,
|
390
425
|
}
|
391
426
|
|
392
427
|
ApplicationInstance.propTypes = {
|
@@ -408,7 +443,9 @@ ApplicationInstance.propTypes = {
|
|
408
443
|
closeForemanParameterSelectionModal: PropTypes.func,
|
409
444
|
openAnsibleParameterSelectionModal: PropTypes.func,
|
410
445
|
closeAnsibleParameterSelectionModal: PropTypes.func,
|
446
|
+
changeParameterSelectionMode: PropTypes.func,
|
411
447
|
parametersData: PropTypes.object,
|
448
|
+
paramEditMode: PropTypes.bool,
|
412
449
|
};
|
413
450
|
|
414
451
|
export default ApplicationInstance;
|
@@ -29,6 +29,7 @@ import {
|
|
29
29
|
APPLICATION_INSTANCE_LOAD_APPLICATION_DEFINITION_REQUEST,
|
30
30
|
APPLICATION_INSTANCE_LOAD_APPLICATION_DEFINITION_SUCCESS,
|
31
31
|
APPLICATION_INSTANCE_LOAD_APPLICATION_DEFINITION_FAILURE,
|
32
|
+
APPLICATION_INSTANCE_CHANGE_PARAMETER_SELECTION_MODE,
|
32
33
|
} from './ApplicationInstanceConstants';
|
33
34
|
|
34
35
|
export const initApplicationInstance = (
|
@@ -237,3 +238,10 @@ export const closeAnsibleParameterSelectionModal = (additionalData) => dispatch
|
|
237
238
|
setModalClosed({ id: 'AppInstanceAnsibleParamSelection' })
|
238
239
|
);
|
239
240
|
}
|
241
|
+
|
242
|
+
export const changeParameterSelectionMode = (additionalData) => ({
|
243
|
+
type: APPLICATION_INSTANCE_CHANGE_PARAMETER_SELECTION_MODE,
|
244
|
+
payload: {
|
245
|
+
...additionalData,
|
246
|
+
},
|
247
|
+
})
|
@@ -12,3 +12,4 @@ export const APPLICATION_INSTANCE_FOREMAN_PARAMETER_SELECTION_MODAL_OPEN = 'APPL
|
|
12
12
|
export const APPLICATION_INSTANCE_FOREMAN_PARAMETER_SELECTION_MODAL_CLOSE = 'APPLICATION_INSTANCE_FOREMAN_PARAMETER_SELECTION_MODAL_CLOSE';
|
13
13
|
export const APPLICATION_INSTANCE_ANSIBLE_PARAMETER_SELECTION_MODAL_OPEN = 'APPLICATION_INSTANCE_ANSIBLE_PARAMETER_SELECTION_MODAL_OPEN';
|
14
14
|
export const APPLICATION_INSTANCE_ANSIBLE_PARAMETER_SELECTION_MODAL_CLOSE = 'APPLICATION_INSTANCE_ANSIBLE_PARAMETER_SELECTION_MODAL_CLOSE';
|
15
|
+
export const APPLICATION_INSTANCE_CHANGE_PARAMETER_SELECTION_MODE = 'APPLICATION_INSTANCE_CHANGE_PARAMETER_SELECTION_MODE';
|
@@ -21,6 +21,7 @@ import {
|
|
21
21
|
APPLICATION_INSTANCE_FOREMAN_PARAMETER_SELECTION_MODAL_CLOSE,
|
22
22
|
APPLICATION_INSTANCE_ANSIBLE_PARAMETER_SELECTION_MODAL_OPEN,
|
23
23
|
APPLICATION_INSTANCE_ANSIBLE_PARAMETER_SELECTION_MODAL_CLOSE,
|
24
|
+
APPLICATION_INSTANCE_CHANGE_PARAMETER_SELECTION_MODE,
|
24
25
|
} from './ApplicationInstanceConstants';
|
25
26
|
|
26
27
|
import {
|
@@ -133,13 +134,23 @@ const applicationInstanceConf = (state = initialState, action) => {
|
|
133
134
|
return state;
|
134
135
|
}
|
135
136
|
|
137
|
+
// hostnames are lower case
|
138
|
+
thisHost.hostname = thisHost.hostname.toLowerCase();
|
139
|
+
|
140
|
+
const hostnameRegex = /^[0-9a-z]([0-9a-z\-]{0,61}[0-9a-z])$/;
|
141
|
+
|
142
|
+
if (thisHost.hostname.match(hostnameRegex) == undefined) {
|
143
|
+
window.alert("The hostname uses not allowed characters. See https://en.wikipedia.org/wiki/Hostname#Syntax for more details.")
|
144
|
+
return state;
|
145
|
+
}
|
146
|
+
|
136
147
|
if (thisHost.service == '') {
|
137
|
-
window.alert("Every host needs to be assigned to a service");
|
148
|
+
window.alert("Every host needs to be assigned to a service.");
|
138
149
|
return state;
|
139
150
|
}
|
140
151
|
|
141
152
|
if (state.hosts.filter(v => v.hostname === thisHost.hostname && v.id != thisHost.id).length > 0) {
|
142
|
-
window.alert("Host name already used
|
153
|
+
window.alert("Host name already used in this Application Instance. Please make sure that every host name is unique.");
|
143
154
|
return state;
|
144
155
|
}
|
145
156
|
|
@@ -287,6 +298,9 @@ const applicationInstanceConf = (state = initialState, action) => {
|
|
287
298
|
}
|
288
299
|
return state.merge(newState);
|
289
300
|
}
|
301
|
+
case APPLICATION_INSTANCE_CHANGE_PARAMETER_SELECTION_MODE: {
|
302
|
+
return state.merge({ paramEditMode: payload.mode });
|
303
|
+
}
|
290
304
|
default:
|
291
305
|
return state;
|
292
306
|
}
|
@@ -7,3 +7,4 @@ export const selectColumns = state => applicationInstanceConf(state).columns;
|
|
7
7
|
export const selectServices = state => applicationInstanceConf(state).services;
|
8
8
|
export const selectParametersData = state => applicationInstanceConf(state).parametersData;
|
9
9
|
export const selectAnsibleVarsAll = state => applicationInstanceConf(state).ansibleVarsAll;
|
10
|
+
export const selectParamEditMode = state => applicationInstanceConf(state).paramEditMode;
|
@@ -13,6 +13,7 @@ import {
|
|
13
13
|
selectColumns,
|
14
14
|
selectParametersData,
|
15
15
|
selectAnsibleVarsAll,
|
16
|
+
selectParamEditMode,
|
16
17
|
} from './ApplicationInstanceSelectors';
|
17
18
|
|
18
19
|
const mapStateToProps = state => ({
|
@@ -23,6 +24,7 @@ const mapStateToProps = state => ({
|
|
23
24
|
columns: selectColumns(state),
|
24
25
|
parametersData: selectParametersData(state),
|
25
26
|
ansibleVarsAll: selectAnsibleVarsAll(state),
|
27
|
+
paramEditMode: selectParamEditMode(state),
|
26
28
|
});
|
27
29
|
|
28
30
|
const mapDispatchToProps = dispatch =>
|