foreman_remote_execution 3.3.2 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +2 -1
  3. data/app/assets/stylesheets/foreman_remote_execution/job_invocations.scss +6 -5
  4. data/app/controllers/api/v2/job_invocations_controller.rb +3 -2
  5. data/app/controllers/job_invocations_controller.rb +22 -8
  6. data/app/lib/actions/remote_execution/run_host_job.rb +1 -1
  7. data/app/lib/actions/remote_execution/run_hosts_job.rb +1 -1
  8. data/app/lib/foreman_remote_execution/renderer/scope/input.rb +35 -0
  9. data/app/models/concerns/foreman_remote_execution/orchestration/ssh.rb +11 -4
  10. data/app/models/job_invocation.rb +6 -3
  11. data/app/models/job_invocation_composer.rb +2 -2
  12. data/app/models/remote_execution_provider.rb +2 -2
  13. data/app/models/setting/remote_execution.rb +2 -2
  14. data/app/models/ssh_execution_provider.rb +1 -1
  15. data/app/services/default_proxy_proxy_selector.rb +3 -1
  16. data/app/views/api/v2/job_invocations/main.json.rabl +2 -2
  17. data/app/views/job_invocations/_card_target_hosts.html.erb +1 -1
  18. data/app/views/job_invocations/_form.html.erb +1 -1
  19. data/app/views/job_invocations/_tab_hosts.html.erb +1 -20
  20. data/app/views/job_invocations/index.html.erb +2 -1
  21. data/app/views/job_invocations/show.html.erb +9 -0
  22. data/app/views/job_invocations/show.js.erb +5 -0
  23. data/app/views/job_invocations/show.json.erb +2 -1
  24. data/app/views/templates/ssh/package_action.erb +1 -0
  25. data/app/views/templates/ssh/puppet_agent_disable.erb +3 -0
  26. data/app/views/templates/ssh/puppet_agent_enable.erb +3 -0
  27. data/app/views/templates/ssh/puppet_install_modules_from_forge.erb +3 -0
  28. data/app/views/templates/ssh/puppet_run_once.erb +3 -0
  29. data/db/migrate/20200623073022_rename_sudo_password_to_effective_user_password.rb +34 -0
  30. data/db/seeds.d/20-permissions.rb +9 -0
  31. data/lib/foreman_remote_execution/engine.rb +4 -1
  32. data/lib/foreman_remote_execution/version.rb +1 -1
  33. data/test/functional/api/v2/job_invocations_controller_test.rb +65 -2
  34. data/test/functional/job_invocations_controller_test.rb +71 -0
  35. data/test/models/orchestration/ssh_test.rb +1 -1
  36. data/test/support/remote_execution_helper.rb +5 -0
  37. data/test/unit/actions/run_host_job_test.rb +3 -3
  38. data/test/unit/actions/run_hosts_job_test.rb +1 -1
  39. data/test/unit/job_invocation_composer_test.rb +5 -5
  40. data/test/unit/remote_execution_provider_test.rb +6 -6
  41. data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +2 -0
  42. data/webpack/__mocks__/foremanReact/components/SearchBar.js +2 -0
  43. data/webpack/__mocks__/foremanReact/constants.js +21 -0
  44. data/webpack/__mocks__/foremanReact/redux/API/APISelectors.js +2 -0
  45. data/webpack/__mocks__/foremanReact/redux/middlewares/IntervalMiddleware/IntervalSelectors.js +1 -0
  46. data/webpack/react_app/components/TargetingHosts/TargetingHosts.js +21 -15
  47. data/webpack/react_app/components/TargetingHosts/TargetingHostsHelpers.js +10 -0
  48. data/webpack/react_app/components/TargetingHosts/TargetingHostsPage.js +62 -0
  49. data/webpack/react_app/components/TargetingHosts/TargetingHostsPage.scss +6 -0
  50. data/webpack/react_app/components/TargetingHosts/TargetingHostsSelectors.js +10 -2
  51. data/webpack/react_app/components/TargetingHosts/__tests__/TargetingHostsPage.test.js +9 -0
  52. data/webpack/react_app/components/TargetingHosts/__tests__/TargetingHostsSelectors.test.js +26 -0
  53. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHosts.test.js.snap +16 -1
  54. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsPage.test.js.snap +68 -0
  55. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsSelectors.test.js.snap +11 -0
  56. data/webpack/react_app/components/TargetingHosts/__tests__/fixtures.js +35 -19
  57. data/webpack/react_app/components/TargetingHosts/index.js +73 -13
  58. metadata +18 -3
  59. data/webpack/react_app/components/TargetingHosts/TargetingHostsActions.js +0 -8
@@ -0,0 +1,10 @@
1
+ import { getURI } from 'foremanReact/common/urlHelpers';
2
+
3
+ export const getApiUrl = (searchQuery, pagination) => {
4
+ const baseUrl = getURI()
5
+ .search('')
6
+ .addQuery('page', pagination.page)
7
+ .addQuery('per_page', pagination.perPage);
8
+
9
+ return searchQuery ? baseUrl.addQuery('search', searchQuery) : baseUrl;
10
+ };
@@ -0,0 +1,62 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Grid } from 'patternfly-react';
4
+
5
+ import SearchBar from 'foremanReact/components/SearchBar';
6
+ import Pagination from 'foremanReact/components/Pagination/PaginationWrapper';
7
+ import { getControllerSearchProps } from 'foremanReact/constants';
8
+
9
+ import TargetingHosts from './TargetingHosts';
10
+ import './TargetingHostsPage.scss';
11
+
12
+ const TargetingHostsPage = ({
13
+ handleSearch,
14
+ searchQuery,
15
+ apiStatus,
16
+ items,
17
+ totalHosts,
18
+ pagination,
19
+ handlePagination,
20
+ }) => (
21
+ <div id="targeting_hosts">
22
+ <Grid.Row>
23
+ <Grid.Col md={6} className="title_filter">
24
+ <SearchBar
25
+ onSearch={query => handleSearch(query)}
26
+ data={{
27
+ ...getControllerSearchProps('hosts'),
28
+ autocomplete: {
29
+ id: 'targeting_hosts_search',
30
+ searchQuery,
31
+ url: '/hosts/auto_complete_search',
32
+ useKeyShortcuts: true,
33
+ },
34
+ bookmarks: {},
35
+ }}
36
+ />
37
+ </Grid.Col>
38
+ </Grid.Row>
39
+ <br />
40
+ <TargetingHosts apiStatus={apiStatus} items={items} />
41
+ <Pagination
42
+ viewType="list"
43
+ itemCount={totalHosts}
44
+ pagination={pagination}
45
+ onChange={args => handlePagination(args)}
46
+ dropdownButtonId="targeting-hosts-pagination-dropdown"
47
+ className="targeting-hosts-pagination"
48
+ />
49
+ </div>
50
+ );
51
+
52
+ TargetingHostsPage.propTypes = {
53
+ handleSearch: PropTypes.func.isRequired,
54
+ searchQuery: PropTypes.string.isRequired,
55
+ apiStatus: PropTypes.string.isRequired,
56
+ items: PropTypes.array.isRequired,
57
+ totalHosts: PropTypes.number.isRequired,
58
+ pagination: PropTypes.object.isRequired,
59
+ handlePagination: PropTypes.func.isRequired,
60
+ };
61
+
62
+ export default TargetingHostsPage;
@@ -0,0 +1,6 @@
1
+ .targeting-hosts-pagination {
2
+ margin-top: -7px;
3
+ }
4
+ #targeting_hosts {
5
+ min-height: 350px;
6
+ }
@@ -2,11 +2,19 @@ import {
2
2
  selectAPIStatus,
3
3
  selectAPIResponse,
4
4
  } from 'foremanReact/redux/API/APISelectors';
5
+ import { selectDoesIntervalExist } from 'foremanReact/redux/middlewares/IntervalMiddleware/IntervalSelectors';
6
+
5
7
  import { TARGETING_HOSTS } from './TargetingHostsConsts';
6
8
 
7
9
  export const selectItems = state =>
8
10
  selectAPIResponse(state, TARGETING_HOSTS).hosts || [];
9
11
 
10
12
  export const selectAutoRefresh = state =>
11
- selectAPIResponse(state, TARGETING_HOSTS).autoRefresh;
12
- export const selectStatus = state => selectAPIStatus(state, TARGETING_HOSTS);
13
+ selectAPIResponse(state, TARGETING_HOSTS).autoRefresh || '';
14
+
15
+ export const selectApiStatus = state => selectAPIStatus(state, TARGETING_HOSTS);
16
+ export const selectTotalHosts = state =>
17
+ selectAPIResponse(state, TARGETING_HOSTS).total_hosts || 0;
18
+
19
+ export const selectIntervalExists = state =>
20
+ selectDoesIntervalExist(state, TARGETING_HOSTS);
@@ -0,0 +1,9 @@
1
+ import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2
+ import TargetingHostsPage from '../TargetingHostsPage';
3
+ import { TargetingHostsPageFixtures } from './fixtures';
4
+
5
+ describe('TargetingHostsPage', () =>
6
+ testComponentSnapshotsWithFixtures(
7
+ TargetingHostsPage,
8
+ TargetingHostsPageFixtures
9
+ ));
@@ -0,0 +1,26 @@
1
+ import { testSelectorsSnapshotWithFixtures } from '@theforeman/test';
2
+
3
+ import {
4
+ selectItems,
5
+ selectAutoRefresh,
6
+ selectApiStatus,
7
+ selectTotalHosts,
8
+ selectIntervalExists,
9
+ } from '../TargetingHostsSelectors';
10
+
11
+ const state = {
12
+ hosts: [],
13
+ autoRefresh: 'true',
14
+ total_hosts: 0,
15
+ };
16
+
17
+ const fixtures = {
18
+ 'should return hosts': () => selectItems(state),
19
+ 'should return autoRefresh': () => selectAutoRefresh(state),
20
+ 'should return apiStatus': () => selectApiStatus(state),
21
+ 'should return totalHosts': () => selectTotalHosts(state),
22
+ 'should return intervalExists': () => selectIntervalExists(state),
23
+ };
24
+
25
+ describe('TargetingHostsSelectors', () =>
26
+ testSelectorsSnapshotWithFixtures(fixtures));
@@ -33,6 +33,13 @@ exports[`TargetingHosts renders 1`] = `
33
33
  name="host"
34
34
  status="success"
35
35
  />
36
+ <HostItem
37
+ actions={Array []}
38
+ key="host2"
39
+ link="/link2"
40
+ name="host2"
41
+ status="success"
42
+ />
36
43
  </tbody>
37
44
  </table>
38
45
  </div>
@@ -74,7 +81,15 @@ exports[`TargetingHosts renders with loading 1`] = `
74
81
  </th>
75
82
  </tr>
76
83
  </thead>
77
- <tbody />
84
+ <tbody>
85
+ <tr>
86
+ <td
87
+ colSpan="3"
88
+ >
89
+ No hosts found.
90
+ </td>
91
+ </tr>
92
+ </tbody>
78
93
  </table>
79
94
  </div>
80
95
  </LoadingState>
@@ -0,0 +1,68 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`TargetingHostsPage renders 1`] = `
4
+ <div
5
+ id="targeting_hosts"
6
+ >
7
+ <Row
8
+ bsClass="row"
9
+ componentClass="div"
10
+ >
11
+ <Col
12
+ bsClass="col"
13
+ className="title_filter"
14
+ componentClass="div"
15
+ md={6}
16
+ >
17
+ <SearchBar
18
+ data={
19
+ Object {
20
+ "autocomplete": Object {
21
+ "id": "targeting_hosts_search",
22
+ "searchQuery": "",
23
+ "url": "/hosts/auto_complete_search",
24
+ "useKeyShortcuts": true,
25
+ },
26
+ "bookmarks": Object {},
27
+ "controller": "hosts",
28
+ }
29
+ }
30
+ onSearch={[Function]}
31
+ />
32
+ </Col>
33
+ </Row>
34
+ <br />
35
+ <TargetingHosts
36
+ apiStatus="RESOLVED"
37
+ items={
38
+ Array [
39
+ Object {
40
+ "actions": Array [],
41
+ "link": "/link",
42
+ "name": "host",
43
+ "status": "success",
44
+ },
45
+ Object {
46
+ "actions": Array [],
47
+ "link": "/link2",
48
+ "name": "host2",
49
+ "status": "success",
50
+ },
51
+ ]
52
+ }
53
+ />
54
+ <PaginationWrapper
55
+ className="targeting-hosts-pagination"
56
+ dropdownButtonId="targeting-hosts-pagination-dropdown"
57
+ itemCount={1}
58
+ onChange={[Function]}
59
+ pagination={
60
+ Object {
61
+ "page": 1,
62
+ "perPage": 20,
63
+ }
64
+ }
65
+ viewType="list"
66
+ />
67
+ </div>
68
+ `;
@@ -0,0 +1,11 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`TargetingHostsSelectors should return apiStatus 1`] = `"RESOLVED"`;
4
+
5
+ exports[`TargetingHostsSelectors should return autoRefresh 1`] = `"true"`;
6
+
7
+ exports[`TargetingHostsSelectors should return hosts 1`] = `Array []`;
8
+
9
+ exports[`TargetingHostsSelectors should return intervalExists 1`] = `false`;
10
+
11
+ exports[`TargetingHostsSelectors should return totalHosts 1`] = `0`;
@@ -1,3 +1,18 @@
1
+ const items = [
2
+ {
3
+ name: 'host',
4
+ link: '/link',
5
+ status: 'success',
6
+ actions: [],
7
+ },
8
+ {
9
+ name: 'host2',
10
+ link: '/link2',
11
+ status: 'success',
12
+ actions: [],
13
+ },
14
+ ];
15
+
1
16
  export const HostItemFixtures = {
2
17
  renders: {
3
18
  name: 'Host1',
@@ -15,29 +30,30 @@ export const HostStatusFixtures = {
15
30
 
16
31
  export const TargetingHostsFixtures = {
17
32
  renders: {
18
- status: '',
19
- items: [
20
- {
21
- name: 'host',
22
- link: '/link',
23
- status: 'success',
24
- actions: [],
25
- },
26
- ],
33
+ apiStatus: 'RESOLVED',
34
+ items,
27
35
  },
28
36
  'renders with error': {
29
- status: 'ERROR',
30
- items: [
31
- {
32
- name: 'host',
33
- link: '/link',
34
- status: 'success',
35
- actions: [],
36
- },
37
- ],
37
+ apiStatus: 'ERROR',
38
+ items,
38
39
  },
39
40
  'renders with loading': {
40
- status: '',
41
+ apiStatus: 'PENDING',
41
42
  items: [],
42
43
  },
43
44
  };
45
+
46
+ export const TargetingHostsPageFixtures = {
47
+ renders: {
48
+ handleSearch: () => {},
49
+ searchQuery: '',
50
+ apiStatus: 'RESOLVED',
51
+ items,
52
+ totalHosts: 1,
53
+ pagination: {
54
+ page: 1,
55
+ perPage: 20,
56
+ },
57
+ handlePagination: () => {},
58
+ },
59
+ };
@@ -1,37 +1,97 @@
1
- import React, { useEffect } from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
  import { useSelector, useDispatch } from 'react-redux';
3
- import { stopInterval } from 'foremanReact/redux/middlewares/IntervalMiddleware';
4
- import TargetingHosts from './TargetingHosts';
3
+
4
+ import { get } from 'foremanReact/redux/API';
5
+ import { useForemanSettings } from 'foremanReact/Root/Context/ForemanContext';
6
+ import {
7
+ withInterval,
8
+ stopInterval,
9
+ } from 'foremanReact/redux/middlewares/IntervalMiddleware';
5
10
 
6
11
  import {
7
12
  selectItems,
8
- selectStatus,
13
+ selectApiStatus,
9
14
  selectAutoRefresh,
15
+ selectTotalHosts,
16
+ selectIntervalExists,
10
17
  } from './TargetingHostsSelectors';
11
- import { getData } from './TargetingHostsActions';
18
+ import { getApiUrl } from './TargetingHostsHelpers';
12
19
  import { TARGETING_HOSTS } from './TargetingHostsConsts';
20
+ import TargetingHostsPage from './TargetingHostsPage';
13
21
 
14
22
  const WrappedTargetingHosts = () => {
15
23
  const dispatch = useDispatch();
24
+ const { perPage, perPageOptions } = useForemanSettings();
25
+
16
26
  const autoRefresh = useSelector(selectAutoRefresh);
17
27
  const items = useSelector(selectItems);
18
- const status = useSelector(selectStatus);
28
+ const apiStatus = useSelector(selectApiStatus);
29
+ const totalHosts = useSelector(selectTotalHosts);
30
+ const [searchQuery, setSearchQuery] = useState('');
31
+ const [pagination, setPagination] = useState({
32
+ page: 1,
33
+ perPage,
34
+ perPageOptions,
35
+ });
36
+ const [apiUrl, setApiUrl] = useState(getApiUrl(searchQuery, pagination));
37
+ const intervalExists = useSelector(selectIntervalExists);
19
38
 
20
- useEffect(() => {
21
- dispatch(getData());
39
+ const handleSearch = query => {
40
+ const defaultPagination = { page: 1, perPage: pagination.perPage };
41
+ stopApiInterval();
22
42
 
23
- return () => {
43
+ setApiUrl(getApiUrl(query, defaultPagination));
44
+ setSearchQuery(query);
45
+ setPagination(defaultPagination);
46
+ };
47
+
48
+ const handlePagination = args => {
49
+ stopApiInterval();
50
+ setPagination(args);
51
+ setApiUrl(getApiUrl(searchQuery, args));
52
+ };
53
+
54
+ const stopApiInterval = () => {
55
+ if (intervalExists) {
24
56
  dispatch(stopInterval(TARGETING_HOSTS));
25
- };
26
- }, [dispatch]);
57
+ }
58
+ };
59
+
60
+ const getData = url =>
61
+ withInterval(
62
+ get({
63
+ key: TARGETING_HOSTS,
64
+ url,
65
+ handleError: () => {
66
+ dispatch(stopInterval(TARGETING_HOSTS));
67
+ },
68
+ }),
69
+ 1000
70
+ );
27
71
 
28
72
  useEffect(() => {
73
+ dispatch(getData(apiUrl));
74
+
29
75
  if (autoRefresh === 'false') {
30
76
  dispatch(stopInterval(TARGETING_HOSTS));
31
77
  }
32
- }, [autoRefresh, dispatch]);
33
78
 
34
- return <TargetingHosts status={status} items={items} />;
79
+ return () => {
80
+ dispatch(stopInterval(TARGETING_HOSTS));
81
+ };
82
+ }, [dispatch, apiUrl, autoRefresh]);
83
+
84
+ return (
85
+ <TargetingHostsPage
86
+ handleSearch={handleSearch}
87
+ searchQuery={searchQuery}
88
+ apiStatus={apiStatus}
89
+ items={items}
90
+ totalHosts={totalHosts}
91
+ pagination={pagination}
92
+ handlePagination={handlePagination}
93
+ />
94
+ );
35
95
  };
36
96
 
37
97
  export default WrappedTargetingHosts;
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_remote_execution
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.2
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foreman Remote Execution team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-23 00:00:00.000000000 Z
11
+ date: 2020-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deface
@@ -249,6 +249,7 @@ files:
249
249
  - app/views/job_invocations/new.html.erb
250
250
  - app/views/job_invocations/refresh.js.erb
251
251
  - app/views/job_invocations/show.html.erb
252
+ - app/views/job_invocations/show.js.erb
252
253
  - app/views/job_invocations/show.json.erb
253
254
  - app/views/job_invocations/welcome.html.erb
254
255
  - app/views/job_templates/_custom_tab_headers.html.erb
@@ -322,7 +323,9 @@ files:
322
323
  - db/migrate/20180411160809_add_sudo_password_to_job_invocation.rb
323
324
  - db/migrate/20180913101042_add_randomized_ordering_to_targeting.rb
324
325
  - db/migrate/20190111153330_remove_remote_execution_without_proxy_setting.rb
326
+ - db/migrate/20200623073022_rename_sudo_password_to_effective_user_password.rb
325
327
  - db/seeds.d/100-assign_features_with_templates.rb
328
+ - db/seeds.d/20-permissions.rb
326
329
  - db/seeds.d/50-notification_blueprints.rb
327
330
  - db/seeds.d/60-ssh_proxy_feature.rb
328
331
  - db/seeds.d/70-job_templates.rb
@@ -376,6 +379,7 @@ files:
376
379
  - test/functional/job_templates_controller_test.rb
377
380
  - test/helpers/remote_execution_helper_test.rb
378
381
  - test/models/orchestration/ssh_test.rb
382
+ - test/support/remote_execution_helper.rb
379
383
  - test/test_plugin_helper.rb
380
384
  - test/unit/actions/run_host_job_test.rb
381
385
  - test/unit/actions/run_hosts_job_test.rb
@@ -394,19 +398,29 @@ files:
394
398
  - test/unit/targeting_test.rb
395
399
  - test/unit/template_invocation_input_value_test.rb
396
400
  - webpack/__mocks__/foremanReact/common/I18n.js
401
+ - webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js
402
+ - webpack/__mocks__/foremanReact/components/SearchBar.js
397
403
  - webpack/__mocks__/foremanReact/components/common/ActionButtons/ActionButtons.js
398
404
  - webpack/__mocks__/foremanReact/constants.js
405
+ - webpack/__mocks__/foremanReact/redux/API/APISelectors.js
406
+ - webpack/__mocks__/foremanReact/redux/middlewares/IntervalMiddleware/IntervalSelectors.js
399
407
  - webpack/index.js
400
408
  - webpack/react_app/components/TargetingHosts/TargetingHosts.js
401
- - webpack/react_app/components/TargetingHosts/TargetingHostsActions.js
402
409
  - webpack/react_app/components/TargetingHosts/TargetingHostsConsts.js
410
+ - webpack/react_app/components/TargetingHosts/TargetingHostsHelpers.js
411
+ - webpack/react_app/components/TargetingHosts/TargetingHostsPage.js
412
+ - webpack/react_app/components/TargetingHosts/TargetingHostsPage.scss
403
413
  - webpack/react_app/components/TargetingHosts/TargetingHostsSelectors.js
404
414
  - webpack/react_app/components/TargetingHosts/__tests__/HostItem.test.js
405
415
  - webpack/react_app/components/TargetingHosts/__tests__/HostStatus.test.js
406
416
  - webpack/react_app/components/TargetingHosts/__tests__/TargetingHosts.test.js
417
+ - webpack/react_app/components/TargetingHosts/__tests__/TargetingHostsPage.test.js
418
+ - webpack/react_app/components/TargetingHosts/__tests__/TargetingHostsSelectors.test.js
407
419
  - webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/HostItem.test.js.snap
408
420
  - webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/HostStatus.test.js.snap
409
421
  - webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHosts.test.js.snap
422
+ - webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsPage.test.js.snap
423
+ - webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsSelectors.test.js.snap
410
424
  - webpack/react_app/components/TargetingHosts/__tests__/fixtures.js
411
425
  - webpack/react_app/components/TargetingHosts/components/HostItem.js
412
426
  - webpack/react_app/components/TargetingHosts/components/HostStatus.js
@@ -459,6 +473,7 @@ test_files:
459
473
  - test/functional/job_templates_controller_test.rb
460
474
  - test/helpers/remote_execution_helper_test.rb
461
475
  - test/models/orchestration/ssh_test.rb
476
+ - test/support/remote_execution_helper.rb
462
477
  - test/test_plugin_helper.rb
463
478
  - test/unit/actions/run_host_job_test.rb
464
479
  - test/unit/actions/run_hosts_job_test.rb