foreman_ansible 6.4.1 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/ansible_inventories_controller.rb +1 -1
  3. data/app/graphql/mutations/ansible_variable_overrides/create.rb +26 -0
  4. data/app/graphql/mutations/ansible_variable_overrides/delete.rb +38 -0
  5. data/app/graphql/mutations/ansible_variable_overrides/update.rb +26 -0
  6. data/app/graphql/mutations/hosts/assign_ansible_roles.rb +37 -0
  7. data/app/graphql/presenters/ansible_role_presenter.rb +12 -0
  8. data/app/graphql/presenters/overriden_ansible_variable_presenter.rb +19 -0
  9. data/app/graphql/types/ansible_role.rb +9 -0
  10. data/app/graphql/types/ansible_variable.rb +23 -0
  11. data/app/graphql/types/ansible_variable_override.rb +9 -0
  12. data/app/graphql/types/inherited_ansible_role.rb +13 -0
  13. data/app/graphql/types/overriden_ansible_variable.rb +27 -0
  14. data/app/helpers/foreman_ansible/ansible_roles_data_preparations.rb +22 -22
  15. data/app/models/concerns/foreman_ansible/host_managed_extensions.rb +23 -4
  16. data/app/models/concerns/foreman_ansible/hostgroup_extensions.rb +2 -1
  17. data/app/models/foreman_ansible/ansible_provider.rb +7 -5
  18. data/app/services/foreman_ansible/ansible_report_importer.rb +2 -2
  19. data/app/services/foreman_ansible/inventory_creator.rb +1 -1
  20. data/app/services/foreman_ansible/override_resolver.rb +22 -0
  21. data/app/views/api/v2/ansible_override_values/index.json.rabl +3 -0
  22. data/app/views/api/v2/ansible_variables/show.json.rabl +1 -1
  23. data/app/views/foreman_ansible/ansible_roles/_hostgroup_ansible_roles_button.erb +3 -0
  24. data/app/views/foreman_ansible/job_templates/convert_to_rhel.erb +6 -2
  25. data/app/views/foreman_ansible/job_templates/run_openscap_scans_-_ansible_default.erb +20 -0
  26. data/config/routes.rb +3 -0
  27. data/db/migrate/20210818083407_fix_ansible_setting_category_to_dsl.rb +5 -0
  28. data/lib/foreman_ansible/engine.rb +0 -17
  29. data/lib/foreman_ansible/register.rb +115 -4
  30. data/lib/foreman_ansible/version.rb +1 -1
  31. data/package.json +4 -2
  32. data/test/functional/api/v2/ansible_inventories_controller_test.rb +1 -2
  33. data/test/graphql/mutations/hosts/assign_ansible_roles_mutation_test.rb +96 -0
  34. data/test/graphql/queries/ansible_roles_query_test.rb +35 -0
  35. data/test/unit/ansible_provider_test.rb +3 -6
  36. data/test/unit/concerns/host_managed_extensions_test.rb +8 -0
  37. data/test/unit/concerns/hostgroup_extensions_test.rb +6 -0
  38. data/test/unit/hostgroup_ansible_role_test.rb +13 -0
  39. data/test/unit/services/override_resolver_test.rb +34 -0
  40. data/webpack/components/AnsibleHostDetail/AnsibleHostDetail.js +51 -27
  41. data/webpack/components/AnsibleHostDetail/AnsibleHostDetail.test.js +12 -6
  42. data/webpack/components/AnsibleHostDetail/components/AnsibleHostInventory/AnsibleHostInventory.js +22 -0
  43. data/webpack/components/AnsibleHostDetail/components/AnsibleHostInventory/AnsibleHostInventory.scss +4 -0
  44. data/webpack/components/AnsibleHostDetail/components/AnsibleHostInventory/AnsibleHostInventory.test.js +104 -0
  45. data/webpack/components/AnsibleHostDetail/components/AnsibleHostInventory/index.js +38 -0
  46. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/AnsibleVariableOverrides.scss +3 -0
  47. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/AnsibleVariableOverridesTable.js +238 -0
  48. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/AnsibleVariableOverridesTableHelper.js +111 -0
  49. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/EditableAction.js +161 -0
  50. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/EditableAction.scss +7 -0
  51. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/EditableActionHelper.js +49 -0
  52. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/EditableValue.js +70 -0
  53. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/EditableValueHelper.js +35 -0
  54. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/__test__/AnsibleVariableOverrides.fixtures.js +429 -0
  55. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/__test__/AnsibleVariableOverrides.test.js +71 -0
  56. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/__test__/AnsibleVariableOverridesDelete.test.js +74 -0
  57. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/__test__/AnsibleVariableOverridesUpdate.test.js +188 -0
  58. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/index.js +58 -0
  59. data/webpack/components/AnsibleHostDetail/components/JobsTab/JobsTabHelper.js +79 -0
  60. data/webpack/components/AnsibleHostDetail/components/JobsTab/NewRecurringJobHelper.js +106 -0
  61. data/webpack/components/AnsibleHostDetail/components/JobsTab/NewRecurringJobModal.js +129 -0
  62. data/webpack/components/AnsibleHostDetail/components/JobsTab/NewRecurringJobModal.scss +7 -0
  63. data/webpack/components/AnsibleHostDetail/components/JobsTab/PreviousJobsTable.js +103 -0
  64. data/webpack/components/AnsibleHostDetail/components/JobsTab/RecurringJobsTable.js +96 -0
  65. data/webpack/components/AnsibleHostDetail/components/JobsTab/__test__/JobsTab.fixtures.js +184 -0
  66. data/webpack/components/AnsibleHostDetail/components/JobsTab/__test__/JobsTab.test.js +195 -0
  67. data/webpack/components/AnsibleHostDetail/components/JobsTab/index.js +88 -0
  68. data/webpack/components/AnsibleHostDetail/components/RolesTab/AllRolesModal/AllRolesTable.js +89 -0
  69. data/webpack/components/AnsibleHostDetail/components/RolesTab/AllRolesModal/index.js +80 -0
  70. data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/EditRolesForm.js +90 -0
  71. data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/EditRolesModal.scss +3 -0
  72. data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/EditRolesModalHelper.js +40 -0
  73. data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/index.js +82 -0
  74. data/webpack/components/AnsibleHostDetail/components/RolesTab/RolesTable.js +129 -0
  75. data/webpack/components/AnsibleHostDetail/components/RolesTab/__test__/EditRoles.test.js +85 -0
  76. data/webpack/components/AnsibleHostDetail/components/RolesTab/__test__/RolesTab.fixtures.js +180 -0
  77. data/webpack/components/AnsibleHostDetail/components/RolesTab/__test__/RolesTab.test.js +75 -0
  78. data/webpack/components/AnsibleHostDetail/components/RolesTab/index.js +51 -0
  79. data/webpack/components/AnsibleHostDetail/components/SecondaryTabRoutes.js +60 -0
  80. data/webpack/components/AnsibleHostDetail/components/TabLayout.js +12 -0
  81. data/webpack/components/AnsibleHostDetail/constants.js +9 -0
  82. data/webpack/components/AnsibleHostDetail/helpers.js +4 -0
  83. data/webpack/components/AnsibleRolesAndVariables/__test__/AnsibleRolesAndVariablesImport.test.js +15 -10
  84. data/webpack/components/AnsibleRolesSwitcher/components/AnsibleRole.js +29 -0
  85. data/webpack/components/AnsibleRolesSwitcher/components/AnsibleRole.test.js +3 -0
  86. data/webpack/components/AnsibleRolesSwitcher/components/AvailableRolesList.js +2 -1
  87. data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AnsibleRole.test.js.snap +3 -3
  88. data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AvailableRolesList.test.js.snap +4 -0
  89. data/webpack/components/DualList/DualList.scss +3 -0
  90. data/webpack/components/DualList/ListControls.js +65 -0
  91. data/webpack/components/DualList/ListHeader.js +16 -0
  92. data/webpack/components/DualList/ListItem.js +69 -0
  93. data/webpack/components/DualList/ListPane.js +95 -0
  94. data/webpack/components/DualList/SelectedStatus.js +21 -0
  95. data/webpack/components/DualList/index.js +103 -0
  96. data/webpack/components/ErrorState.js +16 -0
  97. data/webpack/components/withLoading.js +135 -0
  98. data/webpack/components/withPagination.js +0 -0
  99. data/webpack/formHelper.js +131 -0
  100. data/webpack/globalIdHelper.js +13 -0
  101. data/webpack/global_index.js +7 -1
  102. data/webpack/graphql/mutations/assignAnsibleRoles.gql +17 -0
  103. data/webpack/graphql/mutations/cancelRecurringLogic.gql +12 -0
  104. data/webpack/graphql/mutations/createAnsibleVariableOverride.gql +28 -0
  105. data/webpack/graphql/mutations/createJobInvocation.gql +11 -0
  106. data/webpack/graphql/mutations/deleteAnsibleVariableOverride.gql +17 -0
  107. data/webpack/graphql/mutations/updateAnsibleVariableOverride.gql +29 -0
  108. data/webpack/graphql/queries/allAnsibleRoles.gql +13 -0
  109. data/webpack/graphql/queries/ansibleRoles.gql +13 -0
  110. data/webpack/graphql/queries/currentUserAttributes.gql +11 -0
  111. data/webpack/graphql/queries/hostAnsibleRoles.gql +17 -0
  112. data/webpack/graphql/queries/hostAvailableAnsibleRoles.gql +11 -0
  113. data/webpack/graphql/queries/hostVariableOverrides.gql +39 -0
  114. data/webpack/graphql/queries/recurringJobs.gql +28 -0
  115. data/webpack/helpers/pageParamsHelper.js +40 -0
  116. data/webpack/helpers/paginationHelper.js +9 -0
  117. data/webpack/permissionsHelper.js +58 -0
  118. data/webpack/routes/HostgroupJobs/__test__/HostgroupJobs.fixtures.js +63 -0
  119. data/webpack/routes/HostgroupJobs/__test__/HostgroupJobs.test.js +112 -0
  120. data/webpack/routes/HostgroupJobs/index.js +26 -0
  121. data/webpack/routes/routes.js +10 -0
  122. data/webpack/testHelper.js +165 -0
  123. data/webpack/toastHelper.js +4 -0
  124. metadata +127 -54
  125. data/app/assets/images/foreman_ansible/Ansible.png +0 -0
  126. data/app/models/foreman_ansible/fact_name.rb +0 -16
  127. data/app/models/setting/ansible.rb +0 -106
  128. data/app/services/foreman_ansible/fact_importer.rb +0 -99
  129. data/app/services/foreman_ansible/fact_parser.rb +0 -126
  130. data/app/services/foreman_ansible/fact_sparser.rb +0 -37
  131. data/app/services/foreman_ansible/operating_system_parser.rb +0 -102
  132. data/app/services/foreman_ansible/structured_fact_importer.rb +0 -25
  133. data/test/unit/services/fact_importer_test.rb +0 -52
  134. data/test/unit/services/fact_parser_test.rb +0 -281
  135. data/test/unit/services/fact_sparser_test.rb +0 -24
  136. data/test/unit/services/structured_fact_importer_test.rb +0 -30
  137. data/webpack/components/AnsibleRolesAndVariables/__test__/__snapshots__/AnsibleRolesAndVariablesImport.test.js.snap +0 -177
@@ -0,0 +1,49 @@
1
+ import { translate as __, sprintf } from 'foremanReact/common/I18n';
2
+ import { showToast } from '../../../../toastHelper';
3
+
4
+ export const formatError = error =>
5
+ sprintf(
6
+ __(
7
+ 'There was a following error when changing Ansible variable override: %s'
8
+ ),
9
+ error
10
+ );
11
+
12
+ export const joinErrors = errors => errors.map(err => err.message).join(', ');
13
+
14
+ export const onCompleted = (
15
+ dataPath,
16
+ onValidationError,
17
+ toggleWorking,
18
+ onSubmitSuccess
19
+ ) => data => {
20
+ const { errors, overridenAnsibleVariable } = data[dataPath];
21
+ if (Array.isArray(errors) && errors.length > 0) {
22
+ if (
23
+ errors.length === 1 &&
24
+ errors[0].path.join(' ') === 'attributes value'
25
+ ) {
26
+ onValidationError(errors[0].message);
27
+ } else {
28
+ toggleWorking(false);
29
+ showToast({
30
+ type: 'error',
31
+ message: formatError(joinErrors(errors)),
32
+ });
33
+ }
34
+ } else {
35
+ onSubmitSuccess(overridenAnsibleVariable.currentValue.value);
36
+ showToast({
37
+ type: 'success',
38
+ message: __('Ansible variable override successfully changed.'),
39
+ });
40
+ }
41
+ };
42
+
43
+ export const onError = toggleWorking => error => {
44
+ toggleWorking(false);
45
+ showToast({ type: 'error', message: formatError(error.message) });
46
+ };
47
+
48
+ export const hasError = state => state.validation.key === 'error';
49
+ export const createMatcher = value => `fqdn=${value}`;
@@ -0,0 +1,70 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { translate as __ } from 'foremanReact/common/I18n';
4
+
5
+ import { formatValue } from './AnsibleVariableOverridesTableHelper';
6
+
7
+ import {
8
+ TextAreaField,
9
+ TextInputField,
10
+ SelectField,
11
+ } from './EditableValueHelper';
12
+
13
+ const EditableValue = props => {
14
+ if (!props.editing) {
15
+ return formatValue(props.variable);
16
+ }
17
+
18
+ const type = props.variable.parameterType;
19
+
20
+ if (type === 'array' || type === 'hash') {
21
+ return (
22
+ <TextAreaField
23
+ onChange={props.onChange}
24
+ value={props.value}
25
+ validation={props.validation}
26
+ isDisabled={props.working}
27
+ />
28
+ );
29
+ }
30
+
31
+ if (type === 'boolean') {
32
+ return (
33
+ <SelectField
34
+ selectItems={[
35
+ { id: 'trueSelectOpt', value: true, name: __('true') },
36
+ { id: 'falseSelectOpt', value: false, name: __('false') },
37
+ ]}
38
+ onChange={props.onChange}
39
+ validation={props.validation}
40
+ isDisabled={props.working}
41
+ value={props.value}
42
+ />
43
+ );
44
+ }
45
+
46
+ return (
47
+ <TextInputField
48
+ onChange={props.onChange}
49
+ value={props.value}
50
+ validation={props.validation}
51
+ isDisabled={props.working}
52
+ aria-label="Edit override field"
53
+ />
54
+ );
55
+ };
56
+
57
+ EditableValue.propTypes = {
58
+ editing: PropTypes.bool.isRequired,
59
+ variable: PropTypes.object.isRequired,
60
+ onChange: PropTypes.func.isRequired,
61
+ value: PropTypes.any,
62
+ validation: PropTypes.object.isRequired,
63
+ working: PropTypes.bool.isRequired,
64
+ };
65
+
66
+ EditableValue.defaultProps = {
67
+ value: '',
68
+ };
69
+
70
+ export default EditableValue;
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import {
3
+ TextInput,
4
+ TextArea,
5
+ FormGroup,
6
+ FormSelect,
7
+ FormSelectOption,
8
+ } from '@patternfly/react-core';
9
+
10
+ const withFormGroup = Component => componentProps => {
11
+ const { validation, ...rest } = componentProps;
12
+ return (
13
+ <FormGroup
14
+ label=""
15
+ helperTextInvalid={validation.msg}
16
+ validated={validation.key}
17
+ >
18
+ <Component {...rest} validated={validation.key} />
19
+ </FormGroup>
20
+ );
21
+ };
22
+
23
+ export const SelectField = componentProps => {
24
+ const { selectItems, ...rest } = componentProps;
25
+ return (
26
+ <FormSelect className="without_select2" {...rest}>
27
+ {selectItems.map(item => (
28
+ <FormSelectOption key={item.id} value={item.value} label={item.name} />
29
+ ))}
30
+ </FormSelect>
31
+ );
32
+ };
33
+
34
+ export const TextInputField = withFormGroup(TextInput);
35
+ export const TextAreaField = withFormGroup(TextArea);
@@ -0,0 +1,429 @@
1
+ /* eslint-disable max-lines */
2
+ import variableOverridesQuery from '../../../../../graphql/queries/hostVariableOverrides.gql';
3
+ import deleteAnsibleVariableOverride from '../../../../../graphql/mutations/deleteAnsibleVariableOverride.gql';
4
+ import updateAnsibleVariableOverride from '../../../../../graphql/mutations/updateAnsibleVariableOverride.gql';
5
+ import createAnsibleVariableOverride from '../../../../../graphql/mutations/createAnsibleVariableOverride.gql';
6
+ import { admin } from '../../../../../testHelper';
7
+
8
+ export const hostId = 3;
9
+ const hostGlobalId = 'MDE6SG9zdC0z';
10
+ const name = 'centos-random.example.com';
11
+ const match = `fqdn=${name}`;
12
+
13
+ export const hostAttrs = {
14
+ name,
15
+ };
16
+
17
+ const overrideUpdateDeleteId = 'MDE6TG9va3VwVmFsdWUtODQ=';
18
+ const ansibleVariableId = 'MDE6QW5zaWJsZVZhcmlhYmxlLTY2';
19
+ const variableId = 66;
20
+
21
+ const barVariableGlobalId = 'MDE6QW5zaWJsZVZhcmlhYmxlLTU3Mw==';
22
+ const barVariableId = 573;
23
+
24
+ const withFqdnOverride = canEdit => ({
25
+ __typename: 'OverridenAnsibleVariable',
26
+ meta: {
27
+ __typename: 'Meta',
28
+ canEdit,
29
+ },
30
+ id: ansibleVariableId,
31
+ key: 'rectangle',
32
+ defaultValue: 17,
33
+ parameterType: 'integer',
34
+ ansibleRoleName: 'test.role',
35
+ validatorType: '',
36
+ validatorRule: null,
37
+ required: false,
38
+ lookupValues: {
39
+ nodes: [
40
+ {
41
+ __typename: 'LookupValue',
42
+ id: overrideUpdateDeleteId,
43
+ match,
44
+ value: 21,
45
+ omit: false,
46
+ },
47
+ ],
48
+ },
49
+ currentValue: {
50
+ __typename: 'AnsibleVariableOverride',
51
+ value: 21,
52
+ element: 'fqdn',
53
+ elementName: name,
54
+ },
55
+ });
56
+
57
+ const withDomainOverride = canEdit => ({
58
+ __typename: 'OverridenAnsibleVariable',
59
+ meta: {
60
+ __typename: 'Meta',
61
+ canEdit,
62
+ },
63
+ id: 'MDE6QW5zaWJsZVZhcmlhYmxlLTc4',
64
+ key: 'circle',
65
+ defaultValue: 'd',
66
+ parameterType: 'string',
67
+ ansibleRoleName: 'test.role',
68
+ validatorType: '',
69
+ validatorRule: null,
70
+ required: false,
71
+ lookupValues: {
72
+ nodes: [],
73
+ },
74
+ currentValue: {
75
+ __typename: 'AnsibleVariableOverride',
76
+ value: 'c',
77
+ element: 'domain',
78
+ elementName: 'example.com',
79
+ },
80
+ });
81
+
82
+ export const unauthorizedMocks = [
83
+ {
84
+ request: {
85
+ query: variableOverridesQuery,
86
+ variables: {
87
+ id: hostGlobalId,
88
+ match,
89
+ first: 20,
90
+ last: 20,
91
+ },
92
+ },
93
+ result: {
94
+ data: {
95
+ currentUser: admin,
96
+ host: {
97
+ id: hostGlobalId,
98
+ ansibleVariablesWithOverrides: {
99
+ totalCount: 2,
100
+ nodes: [withFqdnOverride(false), withDomainOverride(false)],
101
+ },
102
+ },
103
+ },
104
+ },
105
+ },
106
+ ];
107
+
108
+ export const mocks = [
109
+ {
110
+ request: {
111
+ query: variableOverridesQuery,
112
+ variables: {
113
+ id: hostGlobalId,
114
+ match,
115
+ first: 20,
116
+ last: 20,
117
+ },
118
+ },
119
+ result: {
120
+ data: {
121
+ currentUser: admin,
122
+ host: {
123
+ id: hostGlobalId,
124
+ ansibleVariablesWithOverrides: {
125
+ totalCount: 8,
126
+ nodes: [
127
+ withFqdnOverride(true),
128
+ {
129
+ __typename: 'OverridenAnsibleVariable',
130
+ meta: {
131
+ __typename: 'Meta',
132
+ canEdit: true,
133
+ },
134
+ id: barVariableGlobalId,
135
+ key: 'bar',
136
+ defaultValue: 'a',
137
+ parameterType: 'string',
138
+ ansibleRoleName: 'test.role',
139
+ validatorType: 'list',
140
+ validatorRule: 'a,b,c',
141
+ required: true,
142
+ lookupValues: {
143
+ nodes: [
144
+ {
145
+ __typename: 'LookupValue',
146
+ id: 'MDE6TG9va3VwVmFsdWUtODE=',
147
+ match,
148
+ value: 'b',
149
+ omit: false,
150
+ },
151
+ ],
152
+ },
153
+ currentValue: null,
154
+ },
155
+ {
156
+ __typename: 'OverridenAnsibleVariable',
157
+ meta: {
158
+ __typename: 'Meta',
159
+ canEdit: true,
160
+ },
161
+ id: 'MDE6QW5zaWJsZVZhcmlhYmxlLTY1',
162
+ key: 'square',
163
+ defaultValue: true,
164
+ parameterType: 'boolean',
165
+ ansibleRoleName: 'test.role',
166
+ validatorType: '',
167
+ validatorRule: null,
168
+ required: false,
169
+ lookupValues: {
170
+ nodes: [],
171
+ },
172
+ currentValue: null,
173
+ },
174
+ {
175
+ __typename: 'OverridenAnsibleVariable',
176
+ meta: {
177
+ __typename: 'Meta',
178
+ canEdit: true,
179
+ },
180
+ id: 'MDE6QW5zaWJsZVZhcmlhYmxlLTc4',
181
+ key: 'circle',
182
+ defaultValue: 'd',
183
+ parameterType: 'string',
184
+ ansibleRoleName: 'test.role',
185
+ validatorType: '',
186
+ validatorRule: null,
187
+ required: false,
188
+ lookupValues: {
189
+ nodes: [],
190
+ },
191
+ currentValue: {
192
+ __typename: 'AnsibleVariableOverride',
193
+ value: 'c',
194
+ element: 'domain',
195
+ elementName: 'example.com',
196
+ },
197
+ },
198
+ {
199
+ __typename: 'OverridenAnsibleVariable',
200
+ meta: {
201
+ __typename: 'Meta',
202
+ canEdit: true,
203
+ },
204
+ id: 'MDE6QW5zaWJsZVZhcmlhYmxlLTc5',
205
+ key: 'ellipse',
206
+ defaultValue: ['seven', 'eight'],
207
+ parameterType: 'array',
208
+ ansibleRoleName: 'test.role',
209
+ validatorType: '',
210
+ validatorRule: null,
211
+ required: false,
212
+ lookupValues: {
213
+ nodes: [],
214
+ },
215
+ currentValue: {
216
+ __typename: 'AnsibleVariableOverride',
217
+ value: ['nine'],
218
+ element: 'hostgroup',
219
+ elementName: 'parent hostgroup',
220
+ },
221
+ },
222
+ {
223
+ __typename: 'OverridenAnsibleVariable',
224
+ meta: {
225
+ __typename: 'Meta',
226
+ canEdit: true,
227
+ },
228
+ id: 'MDE6QW5zaWJsZVZhcmlhYmxlLTY2Ng==',
229
+ key: 'spiral',
230
+ defaultValue: { one: 'one', two: 'two' },
231
+ parameterType: 'hash',
232
+ ansibleRoleName: 'test.role',
233
+ validatorType: '',
234
+ validatorRule: null,
235
+ required: false,
236
+ lookupValues: {
237
+ nodes: [],
238
+ },
239
+ currentValue: null,
240
+ },
241
+ {
242
+ __typename: 'OverridenAnsibleVariable',
243
+ meta: {
244
+ __typename: 'Meta',
245
+ canEdit: true,
246
+ },
247
+ id: 'MDE6QW5zaWJsZVZhcmlhYmxlLTY3Mg==',
248
+ key: 'sun',
249
+ defaultValue: "{ one: 'one', two: 'two' }",
250
+ parameterType: 'json',
251
+ ansibleRoleName: 'test.role',
252
+ validatorType: '',
253
+ validatorRule: null,
254
+ required: false,
255
+ lookupValues: {
256
+ nodes: [],
257
+ },
258
+ currentValue: null,
259
+ },
260
+ {
261
+ __typename: 'OverridenAnsibleVariable',
262
+ meta: {
263
+ __typename: 'Meta',
264
+ canEdit: true,
265
+ },
266
+ id: 'MDE6QW5zaWJsZVZhcmlhYmxlLTY3Mw==',
267
+ key: 'moon',
268
+ defaultValue: [
269
+ { hosts: 'all', become: 'true', roles: ['foo'] },
270
+ ],
271
+ parameterType: 'yaml',
272
+ ansibleRoleName: 'test.role',
273
+ validatorType: '',
274
+ validatorRule: null,
275
+ required: false,
276
+ lookupValues: {
277
+ nodes: [],
278
+ },
279
+ currentValue: null,
280
+ },
281
+ ],
282
+ },
283
+ },
284
+ },
285
+ },
286
+ },
287
+ ];
288
+
289
+ export const deleteMocks = [
290
+ {
291
+ request: {
292
+ query: deleteAnsibleVariableOverride,
293
+ variables: { id: overrideUpdateDeleteId, hostId, variableId },
294
+ },
295
+ result: {
296
+ data: {
297
+ deleteAnsibleVariableOverride: {
298
+ errors: [],
299
+ id: overrideUpdateDeleteId,
300
+ overridenAnsibleVariable: {
301
+ __typename: 'OverridenAnsibleVariable',
302
+ id: ansibleVariableId,
303
+ currentValue: {
304
+ __typename: 'AnsibleVariableOverride',
305
+ element: 'os',
306
+ elementName: 'CentOS 7.8',
307
+ value: 101,
308
+ },
309
+ },
310
+ },
311
+ },
312
+ },
313
+ },
314
+ ];
315
+
316
+ const updateMockFactory = (variableValue, returnValue, errors = []) => {
317
+ const mockArray = [
318
+ {
319
+ request: {
320
+ query: updateAnsibleVariableOverride,
321
+ variables: {
322
+ id: overrideUpdateDeleteId,
323
+ hostId,
324
+ ansibleVariableId: variableId,
325
+ value: variableValue,
326
+ match: `fqdn=${hostAttrs.name}`,
327
+ },
328
+ },
329
+ result: {
330
+ data: {
331
+ updateAnsibleVariableOverride: {
332
+ __typename: 'UpdateAnsibleVariableOverrideMutationPayload',
333
+ overridenAnsibleVariable: {
334
+ __typename: 'OverridenAnsibleVariable',
335
+ id: ansibleVariableId,
336
+ lookupValues: {
337
+ __typename: 'LookupValueConnection',
338
+ nodes: [
339
+ {
340
+ __typename: 'LookupValue',
341
+ id: 'MDE6TG9va3VwVmFsdWUtOTY=',
342
+ match: 'fqdn=centos-random.example.com',
343
+ value: returnValue,
344
+ omit: false,
345
+ },
346
+ ],
347
+ },
348
+ currentValue: {
349
+ __typename: 'AnsibleVariableOverride',
350
+ element: 'fqdn',
351
+ elementName: 'centos-random.example.com',
352
+ value: returnValue,
353
+ },
354
+ },
355
+ errors,
356
+ },
357
+ },
358
+ },
359
+ },
360
+ ];
361
+
362
+ return mockArray;
363
+ };
364
+
365
+ const createMockFactory = (variableValue, returnValue, errors = []) => {
366
+ const variables = {
367
+ hostId,
368
+ lookupKeyId: barVariableId,
369
+ value: variableValue,
370
+ match: `fqdn=${hostAttrs.name}`,
371
+ };
372
+
373
+ const mockArray = [
374
+ {
375
+ request: {
376
+ query: createAnsibleVariableOverride,
377
+ variables,
378
+ },
379
+ result: {
380
+ data: {
381
+ createAnsibleVariableOverride: {
382
+ overridenAnsibleVariable: {
383
+ __typename: 'OverridenAnsibleVariable',
384
+ id: ansibleVariableId,
385
+ lookupValues: {
386
+ nodes: [
387
+ {
388
+ __typename: 'LookupValue',
389
+ id: 'MDE6TG9va3VwVmFsdWUtOTY=',
390
+ match: 'fqdn=centos-random.example.com',
391
+ value: returnValue,
392
+ omit: false,
393
+ },
394
+ ],
395
+ },
396
+ currentValue: {
397
+ __typename: 'AnsibleVariableOverride',
398
+ element: 'fqdn',
399
+ elementName: 'centos-random.example.com',
400
+ value: returnValue,
401
+ },
402
+ },
403
+ errors,
404
+ },
405
+ },
406
+ },
407
+ },
408
+ ];
409
+
410
+ return mockArray;
411
+ };
412
+
413
+ export const updateMocks = updateMockFactory('2177', 2177);
414
+ export const createMocks = createMockFactory('b', 'b');
415
+ export const updateErrorMocks = updateMockFactory('2177', 21, [
416
+ {
417
+ path: ['base'],
418
+ message: 'Not enough minerals',
419
+ __typename: 'AttributeError',
420
+ },
421
+ ]);
422
+
423
+ export const updateValidationMocks = updateMockFactory('foo', 21, [
424
+ {
425
+ path: ['attributes', 'value'],
426
+ message: 'is invalid integer',
427
+ __typename: 'AttributeError',
428
+ },
429
+ ]);
@@ -0,0 +1,71 @@
1
+ import React from 'react';
2
+ import { render, screen, waitFor } from '@testing-library/react';
3
+ import '@testing-library/jest-dom';
4
+
5
+ import AnsibleVariableOverrides from '../';
6
+ import {
7
+ mocks,
8
+ unauthorizedMocks,
9
+ hostId,
10
+ hostAttrs,
11
+ } from './AnsibleVariableOverrides.fixtures';
12
+ import {
13
+ withMockedProvider,
14
+ withRedux,
15
+ tick,
16
+ historyMock,
17
+ } from '../../../../../testHelper';
18
+
19
+ const TestComponent = withRedux(withMockedProvider(AnsibleVariableOverrides));
20
+
21
+ describe('AnsibleVariableOverrides', () => {
22
+ it('should show skeleton when page is loading', () => {
23
+ const { container } = render(
24
+ <TestComponent
25
+ hostId={hostId}
26
+ hostAttrs={hostAttrs}
27
+ mocks={mocks}
28
+ history={historyMock}
29
+ />
30
+ );
31
+ expect(
32
+ container.getElementsByClassName('react-loading-skeleton')
33
+ ).toHaveLength(5);
34
+ });
35
+ it('should load', async () => {
36
+ render(
37
+ <TestComponent
38
+ hostId={hostId}
39
+ mocks={mocks}
40
+ hostAttrs={hostAttrs}
41
+ history={historyMock}
42
+ />
43
+ );
44
+ await waitFor(tick);
45
+ expect(screen.getByText('rectangle')).toBeInTheDocument();
46
+ expect(screen.getByText('square')).toBeInTheDocument();
47
+ expect(screen.getByText('circle')).toBeInTheDocument();
48
+ expect(screen.getByText('ellipse')).toBeInTheDocument();
49
+ expect(screen.getByText('sun')).toBeInTheDocument();
50
+ expect(screen.getByText('moon')).toBeInTheDocument();
51
+ });
52
+ it('should not allow editing when user does not have permissions', async () => {
53
+ render(
54
+ <TestComponent
55
+ hostId={hostId}
56
+ mocks={unauthorizedMocks}
57
+ hostAttrs={hostAttrs}
58
+ history={historyMock}
59
+ />
60
+ );
61
+ await waitFor(tick);
62
+ expect(screen.getByText('rectangle')).toBeInTheDocument();
63
+ expect(screen.getByText('circle')).toBeInTheDocument();
64
+ const editBtns = screen.queryAllByRole('button', {
65
+ name: 'Edit override button',
66
+ });
67
+ expect(editBtns).toHaveLength(0);
68
+ const actions = screen.queryAllByRole('button', { name: 'Actions' });
69
+ expect(actions).toHaveLength(0);
70
+ });
71
+ });